LTCD_070816.ISO

This commit is contained in:
Terry A. Davis authored and minexew committed 2018-09-08 21:45:20 +02:00
1 parent d14bbc24f9
commit 0e9364ff4c
506 files changed
+157705 -41812

No files matched your search

+554
View File
@@ -0,0 +1,554 @@
void LockPartition(LTPartition *p)
{
BoolU4 old_preempt=Preempt(OFF);
LTBlkDev *bdev=p->bdev;
CheckLTPartition(p);
if (p->owning_task!=Fs) {
while (Bts(&p->flags,MPEf_LOCKED))
SwapInNext;
if (bdev->type==LTBDT_FDC)
FDCGet(bdev);
p->owning_task=Fs;
}
Preempt(old_preempt);
}
BoolU8 UnlockPartition(LTPartition *p,BoolU4 reset=FALSE)
{
LTBlkDev *bdev=p->bdev;
BoolU4 old_preempt=Preempt(OFF),result=FALSE;
CheckLTPartition(p);
if (p->owning_task==Fs) {
if (reset) {
bdev->flags&=~(LTBDF_INITIALIZED|LTBDF_INIT_IN_PROGRESS);
if (bdev->irq)
LBtr(&sema_irq_busy[bdev->irq],0);
}
p->owning_task=0;
if (bdev->type==LTBDT_FDC)
FDCFree(bdev);
Btr(&p->flags,MPEf_LOCKED);
result=TRUE;
SwapInNext; //Prevent deadlock
}
Preempt(old_preempt);
return result;
}
void AllocMAPBuf(LTPartition *p,U8 num_blks)
{
CheckLTPartition(p);
AFree(p->cur_MAP_blk);
AFree(p->buffered_MAP_dirty_bits);
p->num_buffered_MAP_blks=num_blks;
p->cur_MAP_blk=AMAlloc(num_blks<<BLK_SIZE_BITS);
p->buffered_MAP_dirty_bits=AMAllocZ((num_blks+7)>>3);
p->cur_MAP_blk_num=0;
RBlks(p,p->cur_MAP_blk,p->MAP1,p->num_buffered_MAP_blks,FALSE);
}
void CleanMAPBuf(LTPartition *p,I8 MAP_select=-1)
{
U8 i;
if (MAP_select==-1 || MAP_select==0) {
for (i=0;i<p->num_buffered_MAP_blks;i++)
if (Bt(p->buffered_MAP_dirty_bits,i))
WBlks(p,p->cur_MAP_blk+i<<BLK_SIZE_BITS,p->MAP1+i+p->cur_MAP_blk_num,1,FALSE);
}
if (MAP_select==-1 || MAP_select==1) {
for (i=0;i<p->num_buffered_MAP_blks;i++)
if (Btr(p->buffered_MAP_dirty_bits,i))
WBlks(p,p->cur_MAP_blk+i<<BLK_SIZE_BITS,p->MAP2+i+p->cur_MAP_blk_num,1,FALSE);
}
}
void SetLTBuf(LTPartition *p,U8 c)
{
U8 MAP_blk_num=c>>(BLK_SIZE_BITS+3);
if (MAP_blk_num!=p->cur_MAP_blk_num) {
CleanMAPBuf(p);
p->cur_MAP_blk_num=MAP_blk_num;
RBlks(p,p->cur_MAP_blk,p->MAP1+p->cur_MAP_blk_num,1,FALSE);
}
}
#define ZERO_BUF_SIZE 2048
void WZeroBlks(LTPartition *p,U8 blk,U8 cnt,BoolU4 unlock)
{
U8 n;
U1 *z=MAllocZ(ZERO_BUF_SIZE<<BLK_SIZE_BITS);
while (cnt) {
n=cnt;
if (n>ZERO_BUF_SIZE)
n=ZERO_BUF_SIZE;
WBlks(p,z,blk,n,unlock);
blk+=n;
cnt-=n;
SwapInNext; //Prevent locking
}
Free(z);
}
//Very dangerous
BoolU8 SetDriveType(I1 drive,U8 type=PT_LT)
{
I8 i,j,ext_base,num_partition;
U8 offset,cur_type;
MasterBootStruct mbr;
LTBlkDev *bd=DriveToBlkDev(drive);
num_partition=bd->partition_base-'A';
switch (bd->type) {
case LTBDT_ATA:
offset=0;
ext_base=INVALID_CLUSTER;
while (TRUE) {
ATAReadBlks(bd,&mbr,offset,1);
j=-1;
for (i=0;i<4;i++) {
cur_type=mbr.p[i].type;
if (cur_type) {
if (cur_type==5 || cur_type==0xF)
j=i;
else {
if ((num_partition+'A')==drive) {
mbr.p[i].type=type;
mbr.p[i].active=0x80;
ATAWriteBlks(bd,&mbr,offset,1);
return TRUE;
}
num_partition++;
}
}
}
if (j<0)
break;
if (mbr.p[j].offset==0)
break;
if (ext_base==INVALID_CLUSTER) {
offset=mbr.p[j].offset;
ext_base=offset;
} else
offset=mbr.p[j].offset+ext_base;
}
break;
}
}
BoolU8 InitBlkDev(LTBlkDev *bd,BoolU4 unlock)
{
LTPartition *p=DriveToPartition(bd->partition_base),*p2;
LTBlkDev *bd2;
BoolU4 old_preempt=Preempt(OFF),result=FALSE;
if (!(bd->flags & LTBDF_INITIALIZED)) {
bd->flags|=LTBDF_INITIALIZED |
LTBDF_INIT_IN_PROGRESS;
switch(bd->type) {
case LTBDT_RAM:
bd->RAM_disk=AMAllocZ((bd->max_blk+1)<<BLK_SIZE_BITS);
bd->max_blk=MSize(bd->RAM_disk)>>BLK_SIZE_BITS-1;
p->type=PT_LT;
//TODO: finish unlock?
FormatLT(bd->partition_base,FALSE);
break;
case LTBDT_FDC:
if (!monitor_floppy_tss) {
monitor_floppy_tss=Spawn(&MonitorFDCTsk,"FLOPPY MANAGER");
monitor_floppy_tss->user_data0=bd;
}
bd->max_reads=1;
bd->max_writes=1;
bd->read_freq=750;
bd->write_freq=150;
break;
case LTBDT_ATA:
bd->max_reads=128;
bd->max_writes=1;
bd->read_freq=2000;
bd->write_freq=500;
IDEInit(bd,TRUE);
break;
case LTBDT_ATAPI:
//0xFFFF*4 is too big for my taste
bd->max_reads=0x800*4;
//max of maybe a quarter of disk cache
if (bd->max_reads>ltdc_size*BLK_SIZE/4)
bd->max_reads=(ltdc_size/BLK_SIZE/4) & ~3;
if (bd->max_reads<128)
bd->max_reads=128;
bd->max_writes=0xFFFF*4;
bd->read_freq=1000;
bd->write_freq=250;
IDEInit(bd,TRUE);
p->size=bd->max_blk+1;
break;
case LTBDT_LT_FILE:
if (bd->flags & LTBDF_FORMAT) {
//TODO: finish unlock?
bd->f=FOpen(bd->filename,"wc",p->size);
if (!bd->f)
throw(EXCEPT_PARTITION,1);
//TODO: finish unlock?
FormatLT(bd->partition_base,TRUE);
} else {
bd->f=FOpen(bd->filename,"wc+");
if (!bd->f)
throw(EXCEPT_PARTITION,2);
bd->max_blk=(FSize(bd->f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1;
p->size=bd->max_blk+1;
InitLTPartition(p,unlock);
}
break;
case LTBDT_NON_LT_FILE:
bd->max_reads=128;
bd->max_writes=128;
bd->read_freq=2000;
bd->write_freq=500;
if (bd->flags & LTBDF_FORMAT)
FormatLT(bd->partition_base,TRUE);
else {
p2=DriveToPartition(bd->non_lt_drive);
bd2=p2->bdev;
bd->min_blk=p->offset;
bd->max_blk=p2->offset+p2->size-1; //temp
p->size=p2->size-(p->offset-p2->offset); //temp
InitLTPartition(p,unlock);
bd->max_blk=p->offset+p->size-1;
}
break;
}
if (bd->flags & LTBDF_READ_CACHE)
InvalidateDiskCache(p,unlock);
bd->flags=bd->flags & ~LTBDF_INIT_IN_PROGRESS;
result=TRUE;
}
Preempt(old_preempt);
return result;
}
BoolU8 RBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt,BoolU4 unlock)
{
BoolU4 result=TRUE;
LTBlkDev *bdev=p->bdev;
CheckLTPartition(p);
try {
LockPartition(p);
InitBlkDev(bdev,FALSE);
if ((p->offset && blk<p->offset) || blk+cnt>p->offset+p->size)
throw(EXCEPT_PARTITION,3);
blk+=bdev->offset;
if (bdev->flags & LTBDF_READ_CACHE)
RCache(p,&buf,&blk,&cnt);
if (cnt) {
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SOUND],0))
Sound(bdev->read_freq);
result=p->RBlks(p,buf,blk,cnt);
bdev->last_jiffy=Jiffies;
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SOUND],0))
Sound(0);
if (bdev->flags & LTBDF_READ_CACHE)
LTDCAdd(p,buf,blk,cnt);
if (bdev->type!=LTBDT_RAM)
disk_reads+=cnt;
}
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
return result;
}
BoolU8 WBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt,BoolU4 unlock)
{
BoolU4 result;
LTBlkDev *bdev=p->bdev;
CheckLTPartition(p);
try {
LockPartition(p);
InitBlkDev(bdev,FALSE);
if ((bdev->flags & LTBDF_READ_ONLY) &&
!(bdev->flags & LTBDF_READ_ONLY_OVERRIDE))
throw(EXCEPT_BLKDEV,0);
if ((p->offset && blk<p->offset) || blk+cnt>p->offset+p->size)
throw(EXCEPT_PARTITION,4);
blk+=bdev->offset;
if (cnt) {
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SOUND],0))
Sound(bdev->write_freq);
result=p->WBlks(p,buf,blk,cnt);
bdev->last_jiffy=Jiffies;
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SOUND],0))
Sound(0);
if (bdev->flags & LTBDF_READ_CACHE)
LTDCAdd(p,buf,blk,cnt);
if (bdev->type!=LTBDT_RAM)
disk_writes+=cnt;
}
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
return result;
}
void InvalidateDiskCache(LTPartition *p,BoolU4 unlock)
{
LTBlkDev *bdev=p->bdev;
CheckLTPartition(p);
try {
LockPartition(p);
InitBlkDev(bdev,FALSE);
if (bdev->flags & LTBDF_READ_CACHE)
LTDCInvalidate(p);
if (bdev->type==LTBDT_FDC)
InitLTPartition(p,FALSE);
else if (p->type==PT_ISO9660) {
if (!(bdev->flags & LTBDF_READ_ONLY_OVERRIDE))
InitISOPartition(p,FALSE);
}
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
}
void ChangeDisk(I1 drive_letter=0)
{
LTBlkDev *bdev=DriveToBlkDev(drive_letter);
if (!InitBlkDev(bdev,TRUE) && bdev->flags & LTBDF_REMOVABLE)
InvalidateDiskCache(DriveToPartition(drive_letter),TRUE);
Drive(drive_letter); //TODO: might preempt off
FreeLTFreeList(DriveToPartition(drive_letter),TRUE);
}
void PartitionRep()
{
I8 i;
I1 ch;
U2 u2;
U1 u1;
LTPartition *p;
LTBlkDev *bdev;
coutln "\r\nDefined Partitions:\r\n";
for (i=0;i<32;i++) {
p=&local_partitions[i];
bdev=p->bdev;
if (p->type) {
cout "$$FG,PURPLE$$";
if (p==default_partition)
cout "*";
else
cout " ";
ch=PartitionToDrive(p);
cout ch," ";
if (p->type==PT_LT)
cout "LT ";
else if (p->type==PT_FAT12)
cout "FAT12 ";
else if (p->type==PT_FAT32)
cout "FAT32 ";
else if (p->type==PT_ISO9660)
cout "ISO9660";
else
cout "-------";
cout " ",SysTextSub(bdev->type,"ST_BLKDEV_TYPES")," ";
u2=bdev->base0; cout u2," ";
u1=bdev->irq; cout u1," ";
u1=bdev->unit; coutln u1,"$$FG$$";
coutln p->offset,"-",p->offset+p->size-1;
}
}
}
void ReleaseTaskPartitions()
{
I8 i;
LTPartition *p;
for (i=0;i<32;i++) {
p=&local_partitions[i];
if (p->owning_task==Fs) {
UnlockPartition(p,TRUE);
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SOUND],0))
Sound(0);
}
}
}
U8 NextClusterNum(LTPartition *p,U8 c,U8 cnt,BoolU4 unlock)
{
CheckLTPartition(p);
if (!cnt || !c) return c;
try {
LockPartition(p);
if (p->type==PT_ISO9660 || p->type==PT_LT)
c+=cnt;
else
c=INVALID_CLUSTER;
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
return c;
}
U8 ClusterBlk(LTPartition *p,U8 c)
{
CheckLTPartition(p);
return p->data+c*p->spc;
}
U8 RClusters(LTPartition *p,U1 *buf,U8 c,U8 cnt,BoolU4 unlock,BoolU4 update_display=FALSE)
{
nounusedwarn update_display;
CheckLTPartition(p);
if (!cnt) return c;
try {
LockPartition(p);
if (p->type==PT_ISO9660 || p->type==PT_LT) {
RBlks(p,buf,p->data+c*p->spc,p->spc*cnt,FALSE);
c+=cnt;
} else {
while (cnt && c && c!=INVALID_CLUSTER) {
RBlks(p,buf,p->data+c*p->spc,p->spc,FALSE);
buf+=p->spc<<BLK_SIZE_BITS;
c=NextClusterNum(p,c,1,FALSE);
cnt--;
}
if (cnt)
Debugger;
}
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
return c;
}
BoolU8 ToLTFilename(I1 *dst,I1 *src)
{
MemSet(dst,0,LT_MAX_FILENAME_LEN+1);
if (!CheckFileName(src))
return FALSE;
StrCpy(dst,src);
return TRUE;
}
U8 NameToDirCluster(LTPartition *p,I1 *name,BoolU4 unlock)
{
BoolU4 cont=TRUE;
U8 cur_dir_cluster;
LTDirEntry de;
I1 *buf=NewStr(name),*buf2=NewStr(name);
CheckLTPartition(p);
try {
LockPartition(p);
cur_dir_cluster=p->root_cluster;
while (*buf && cont) {
RemoveFirstSeg(buf,"/",buf2);
if (*buf2) {
if (p->type==PT_LT)
cont=FindLTFile(p,cur_dir_cluster,
buf2,&de,TRUE,FALSE,FALSE);
else if (p->type==PT_ISO9660)
cont=FindISOFile(p,cur_dir_cluster,
buf2,&de,TRUE,FALSE,FALSE);
else cont=FALSE;
cur_dir_cluster=de.cluster;
}
}
if (!cont) {
cout name," ";
PutSysTextErr("ST_FILE_NOT_FOUND");
cur_dir_cluster=0;
}
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
Free(buf);
Free(buf2);
return cur_dir_cluster;
}
U8 NameToParentDirCluster(LTPartition *p,I1 *name,BoolU4 unlock)
{
BoolU4 cont=TRUE;
U8 cur_dir_cluster,cur_dir_cluster2;
LTDirEntry de;
I1 *buf=NewStr(name),*buf2=NewStr(name);
CheckLTPartition(p);
try {
LockPartition(p);
cur_dir_cluster=p->root_cluster;
cur_dir_cluster2=p->root_cluster;
while (*buf && cont) {
cur_dir_cluster2=cur_dir_cluster;
RemoveFirstSeg(buf,"/",buf2);
if (*buf2) {
if (p->type==PT_LT)
cont=FindLTFile(p,cur_dir_cluster,
buf2,&de,TRUE,FALSE,FALSE);
else if (p->type==PT_ISO9660)
cont=FindISOFile(p,cur_dir_cluster,
buf2,&de,TRUE,FALSE,FALSE);
else cont=FALSE;
cur_dir_cluster=de.cluster;
}
}
if (!cont) {
cout name," ";
PutSysTextErr("ST_FILE_NOT_FOUND");
cur_dir_cluster2=0;
}
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
Free(buf);
Free(buf2);
return cur_dir_cluster2;
}
U8 WClusters(LTPartition *p,U1 *buf,U8 c,U8 cnt,BoolU4 unlock,BoolU4 update_display=FALSE)
{
nounusedwarn update_display;
CheckLTPartition(p);
try {
LockPartition(p);
if (p->type==PT_LT) {
WBlks(p,buf,p->data+c*p->spc,p->spc*cnt,FALSE);
c=0;
}
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
return c;
}
//c=0 means first cluster in chain
U8 AllocClusters(LTPartition *p,U8 c,U8 cnt,BoolU4 contiguous,BoolU4 unlock)
{
nounusedwarn contiguous;
if (!cnt)
return c;
CheckLTPartition(p);
if (p->type==PT_LT)
return AllocLTClusters(p,cnt,unlock);
}
+400
View File
@@ -0,0 +1,400 @@
void MapDrive(I1 ch,LTPartition *p)
{
drive_to_partition[ToUpper(ch)-'A']=p;
p->drive=ToUpper(ch);
}
BoolU8 Drive(I1 drive_letter)
{
LTPartition *p;
LTBlkDev *bdev;
BoolU4 different=FALSE;
LTPartition *new_partition=DriveToPartition(drive_letter);
if (!new_partition) {
PutSysTextErr("ST_INVALID_DRIVE");
return FALSE;
}
if (new_partition!=Fs->cur_partition) {
different=TRUE;
Fs->cur_partition=new_partition;
}
p=Fs->cur_partition;
CheckLTPartition(p);
bdev=p->bdev;
CheckLTBlkDev(bdev);
if (different) {
if ((bdev->flags & LTBDF_REMOVABLE) &&
!(bdev->flags & LTBDF_INITIALIZED) )
ChangeDisk(p->drive);
if (bdev->type==LTBDT_RAM ||
bdev->type==LTBDT_NON_LT_FILE ||
bdev->type==LTBDT_LT_FILE)
InitBlkDev(bdev,TRUE);
}
Free(Fs->cur_dir);
Fs->cur_dir=NewStr("/");
if (p->type==PT_ISO9660 || p->type==PT_LT)
return TRUE;
else
return FALSE;
}
BoolU8 Cd(I1 *name,BoolU4 make_dirs=FALSE)
{
I8 maxlen;
BoolU4 result=TRUE;
I1 *change_to_buf,*new_cur_dir,*buf,*hdir;
LTPartition *p;
U8 cur_dir_cluster=0;
if (!*name) return TRUE;
if (name[1]==':') {
if (*name==':') {
if (Fs->cur_partition!=default_partition)
if (!Drive(*name)) return FALSE;
} else {
if (Fs->cur_partition!=
DriveToPartition(*name))
if (!Drive(*name)) return FALSE;
}
name+=2;
}
if (*name=='/' || !*name) {
Free(Fs->cur_dir);
Fs->cur_dir=NewStr("/");
if (*name)
name++;
}
change_to_buf=MStrUtil(name,
SU_REMOVE_LEADING|SU_REMOVE_TRAILING|
SU_DISCARD_PARITY|SU_REMOVE_CTRL_CHARS);
maxlen=StrLen(Fs->cur_dir)+1+StrLen(change_to_buf)+1;
new_cur_dir=MAlloc(maxlen);
buf=MAlloc(maxlen);
StrCpy(new_cur_dir,Fs->cur_dir);
while (*change_to_buf && result) {
RemoveFirstSeg(change_to_buf,"/",buf);
if (!*buf)
StrCpy(new_cur_dir,"/");
else if (!StrCmp(buf,"..")) {
RemoveLastSeg(new_cur_dir,"/");
if (!*new_cur_dir)
StrCpy(new_cur_dir,"/");
} else if (!StrCmp(buf,".")) {
;
} else if (*buf) {
if (!StrCmp(buf,"HOME")) {
hdir=HomeDirStr;
result=Cd(hdir);
Free(new_cur_dir);
new_cur_dir=MAlloc(maxlen+StrLen(hdir));
StrCpy(new_cur_dir,hdir+2);
Free(hdir);
} else {
p=Fs->cur_partition;
cur_dir_cluster=NameToDirCluster(p,new_cur_dir,TRUE);
if (p->type==PT_LT)
result=CdLT(buf,cur_dir_cluster);
else if (p->type==PT_ISO9660)
result=CdISO(buf,cur_dir_cluster);
else result=FALSE;
if (!result && make_dirs) {
Free(Fs->cur_dir);
Fs->cur_dir=NewStr(new_cur_dir);
result=MkDir(buf);
}
if (result) {
if (StrCmp(new_cur_dir,"/"))
StrCat(new_cur_dir,"/");
StrCat(new_cur_dir,buf);
}
}
}
}
Free(Fs->cur_dir);
Fs->cur_dir=NewStr(new_cur_dir);
Free(buf);
Free(change_to_buf);
Free(new_cur_dir);
return result;
}
void DelLTFileAccess(LTFileAccess *fa)
{
LTBlkDev *bdev;
if (!fa) return;
bdev=fa->old_partition->bdev;
if (!(bdev->flags & LTBDF_INIT_IN_PROGRESS)) {
if (fa->old_dir) {
Drive(PartitionToDrive(fa->old_partition));
Cd(fa->old_dir);
}
} else {
Fs->cur_partition=fa->old_partition;
Free(Fs->cur_dir);
Fs->cur_dir=NewStr("/");
}
Free(fa->old_dir);
Free(fa->mask);
Free(fa);
}
LTFileAccess *NewLTFileAccess(I1 *mask,BoolU4 make_mask=FALSE,BoolU4 make_dirs=FALSE)
{
BoolU4 valid=TRUE;
I1 *buf,*my_mask,*temp_mask;
BoolU4 old_silent;
LTFileAccess *fa=MAllocZ(sizeof(LTFileAccess));
my_mask=MStrUtil(mask,
SU_REMOVE_LEADING|SU_REMOVE_TRAILING|
SU_DISCARD_PARITY|SU_REMOVE_CTRL_CHARS);
temp_mask=my_mask;
fa->old_dir=NewStr(Fs->cur_dir);
fa->old_partition=Fs->cur_partition;
if (*my_mask && my_mask[1]==':') {
if (Fs->cur_partition!=DriveToPartition(*my_mask))
if (!Drive(*my_mask)) valid=FALSE;
my_mask+=2;
}
if (StrStr(my_mask,"HOME")) { //TODO
if (Fs->cur_partition!=DriveToPartition(':'))
Drive(':');
}
fa->p=Fs->cur_partition;
CheckLTPartition(fa->p);
buf=MAlloc(StrLen(my_mask)+2);
StrCpy(buf,my_mask);
fa->mask=MAlloc(StrLen(my_mask)+2);
RemoveLastSeg(buf,"/",fa->mask);
if (*my_mask=='/' && !*buf)
StrCpy(buf,"/");
if (*buf)
if (!Cd(buf,make_dirs))
valid=FALSE;
if (valid && make_mask) {
if (!*fa->mask) {
Free(fa->mask);
fa->mask=NewStr("*");
} else {
if (!make_dirs || CheckFileName(fa->mask)) {
old_silent=Silent(ON);
if (Cd(fa->mask,make_dirs)) {
Free(fa->mask);
fa->mask=NewStr("*");
}
Silent(old_silent);
}
}
}
Free(buf);
Free(temp_mask);
if (!valid) {
DelLTFileAccess(fa);
fa=NULL;
// throw(EXCEPT_FILE);
}
return fa;
}
LTDirEntry *FindFiles(I1 *wild,U8 fuf_flags=0)
{
LTDirEntry *result=NULL;
LTFileAccess *fa=NewLTFileAccess(wild,TRUE);
if (fa) {
result=SysFindFiles(fa->mask,fuf_flags);
DelLTFileAccess(fa);
}
return result;
}
BoolU8 IsDir(I1 *dir_name)
{
BoolU4 result=FALSE;
I1 *mask=MSPrintF("%s/*",dir_name);
BoolU4 old_silent=Silent(ON);
LTFileAccess *fa=NewLTFileAccess(mask);
if (fa) {
result=TRUE;
DelLTFileAccess(fa);
}
Free(mask);
Silent(old_silent);
return result;
}
void Dir(I1 *wild=NULL,BoolU4 full=FALSE)
{
I1 *w;
LTFileAccess *fa;
if (!wild)
w=NewStr("*"); //We must do this because of bug that prevents str defaults
else
w=NewStr(wild);
fa=NewLTFileAccess(w,TRUE);
if (fa) {
DirLT(fa->mask,full);
DelLTFileAccess(fa);
}
Free(w);
}
void Del(I1 *wild,BoolU4 print_msg=TRUE)
{
LTFileAccess *fa=NewLTFileAccess(wild);
if (fa) {
if (fa->p->type==PT_LT)
DelLTFiles(fa->p,Fs->cur_dir,fa->mask,FALSE,print_msg);
DelLTFileAccess(fa);
}
}
U1 *ReadFile(I1 *filename,U8 *size=NULL,U8 *attr=NULL,BoolU4 raw=FALSE)
{
SysHashEntry *temph;
I1 *absname;
U1 *result=NULL;
U8 size2=0,attr2=0;
LTFileAccess *fa;
ArcCompressStruct *ac=NULL;
if (attr)
*attr=0;
absname=AbsoluteFileName(filename);
if (!raw && (temph=FindHashEntry(absname,adam_tss->hash_table,HTT_FILE))) {
if (FileAttr(absname) & LT_ATTR_COMPRESSED) {
ac=temph->user_data0;
if (size)
*size=ac->expanded_size;
if (attr)
*attr=FileAttr(absname,*attr);
result=ExpandBuf(ac);
} else { //Not implimented
result=MAlloc(temph->user_data1+1);
MemCpy(result,temph->user_data0,temph->user_data1);
result[temph->user_data1]=0; //Terminate
if (size)
*size=temph->user_data1;
}
} else {
fa=NewLTFileAccess(absname);
if (fa) {
if (fa->p->type==PT_LT)
result=ReadLTFile(fa->p,Fs->cur_dir,fa->mask,&size2,&attr2,raw,&ac);
else if (fa->p->type==PT_ISO9660)
result=ReadISOFile(fa->p,Fs->cur_dir,fa->mask,&size2,&attr2,raw,&ac);
while (!result && StrCmp(Fs->cur_dir,"/")) {
Cd("..");
if (Fs->cur_partition->type==PT_LT)
result=ReadLTFile(fa->p,Fs->cur_dir,fa->mask,&size2,&attr2,raw,&ac);
else if (fa->p->type==PT_ISO9660)
result=ReadISOFile(fa->p,Fs->cur_dir,fa->mask,&size2,&attr2,raw,&ac);
}
if (!result) {
cout filename," ";
PutSysTextErr("ST_FILE_NOT_FOUND");
}
DelLTFileAccess(fa);
}
if (size)
*size=size2;
if (attr)
*attr=attr2;
if (!raw && attr2 & LT_ATTR_RESIDENT) {
temph=AMAllocZ(sizeof(SysHashEntry));
temph->str=ANewStr(absname);
temph->type=HTT_FILE;
temph->use_cnt=0;
temph->source_link=NULL;
temph->user_data0=AMAllocIdentical(ac);
temph->user_data1=size2;
AddSysHashEntry(temph,adam_tss->hash_table);
}
Free(ac);
}
Free(absname);
return result;
}
I1 *ReadTextFile(I1 *filename,U8 *attr=NULL)
{
return ReadFile(filename,NULL,attr);
}
BoolU8 FindFile(I1 *filename,LTDirEntry *rde=NULL,
BoolU4 dir_only=FALSE,BoolU4 file_only=FALSE,BoolU4 scan_parents=FALSE)
{
U8 cur_dir_cluster;
BoolU4 result=FALSE;
LTDirEntry de;
LTFileAccess *fa=NewLTFileAccess(filename);
if (fa) {
cur_dir_cluster=NameToDirCluster(fa->p,Fs->cur_dir,TRUE);
if (fa->p->type==PT_LT)
result=FindLTFile(fa->p,cur_dir_cluster,fa->mask,
&de,dir_only,file_only,TRUE);
else if (fa->p->type==PT_ISO9660)
result=FindISOFile(fa->p,cur_dir_cluster,fa->mask,
&de,dir_only,file_only,TRUE);
if (scan_parents) {
while (!result && StrCmp(Fs->cur_dir,"/")) {
Cd("..");
cur_dir_cluster=NameToDirCluster(fa->p,Fs->cur_dir,TRUE);
if (fa->p->type==PT_LT)
result=FindLTFile(fa->p,cur_dir_cluster,fa->mask,
&de,dir_only,file_only,TRUE);
else if (fa->p->type==PT_ISO9660)
result=FindISOFile(fa->p,cur_dir_cluster,fa->mask,
&de,dir_only,file_only,TRUE);
}
}
DelLTFileAccess(fa);
}
if (result && rde)
MemCpy(rde,&de,sizeof(LTDirEntry));
return result;
}
U8 WriteFile(I1 *filename,U1 *fbuf,
U8 size,LTDate LTdatetime=0,U8 attr=0,BoolU4 raw=FALSE)
{
U8 c=0;
SysHashEntry *temph;
LTFileAccess *fa=NewLTFileAccess(filename);
ArcCompressStruct *ac=NULL;
I1 *absname=AbsoluteFileName(filename);
if (fa) {
if (fa->p->type==PT_LT)
c=WriteLTFile(fa->p,Fs->cur_dir,fa->mask,
fbuf,size,LTdatetime,attr,raw,&ac);
if (temph=FindHashEntry(absname,adam_tss->hash_table,HTT_FILE)) {
AFree(temph->user_data0);
if (!raw && ac && attr & LT_ATTR_RESIDENT) {
temph->user_data0=AMAllocIdentical(ac);
temph->user_data1=size;
} else {
temph->user_data0=0;
temph->type=HTT_INVALID;
}
} else if (!raw && ac && attr & LT_ATTR_RESIDENT) {
temph=AMAllocZ(sizeof(SysHashEntry));
temph->str=ANewStr(absname);
temph->type=HTT_FILE;
temph->use_cnt=0;
temph->source_link=NULL;
temph->user_data0=AMAllocIdentical(ac);
temph->user_data1=size;
AddSysHashEntry(temph,adam_tss->hash_table);
}
Free(ac);
DelLTFileAccess(fa);
}
Free(absname);
return c;
}
void WriteTextFile(I1 *filename,I1 *st,U8 attr=0)
{
WriteFile(filename,st,StrLen(st),0,attr);
}
+338
View File
@@ -0,0 +1,338 @@
void SelectDefaultDrive()
{
default_partition=DriveToPartition(default_drive);
Fs->cur_partition=INVALID_PTR; //Null screws-up cache
Fs->cur_dir=NewStr("/");
ChangeDisk(':');
}
BoolU8 CopySingleZ(I1 *f1,I1 *f2) //Just one file
{
U1 *file_buf=NULL;
U8 size,attr=0;
LTDirEntry de;
if (FindFile(f1,&de,FALSE,TRUE)) {
file_buf=ReadFile(f1,&size,&attr);
attr=FileAttr(f2,attr);
if (file_buf) {
coutln "Copying ",f1," to ",f2;
WriteFile(f2,file_buf,size,de.datetime,attr);
Free(file_buf);
return TRUE;
} else PutSysTextErr("ST_FILE_NOT_FOUND");
} else PutSysTextErr("ST_FILE_NOT_FOUND");
return FALSE;
}
#define COPY_BUF_BLKS 0x400
BoolU8 CopySingle(I1 *f1,I1 *f2) //Just one file
{
U1 *buf;
U8 cnt,n,size,attr1=FileAttr(f1),attr2=FileAttr(f2);
LTFile *in_file=NULL,*out_file=NULL;
U8 xsum=LT_XSUM,i,j;
if (!StrCmp(f1,f2))
return FALSE;
if (attr1!=attr2)
return CopySingleZ(f1,f2);
buf=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
if (attr1 & LT_ATTR_CONTIGUOUS)
in_file=FOpen(f1,"rc");
else
in_file=FOpen(f1,"r");
if (in_file) {
size=FSize(in_file);
cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS;
if (attr2 & LT_ATTR_CONTIGUOUS)
out_file=FOpen(f2,"wc",cnt);
else
out_file=FOpen(f2,"w",cnt);
if (out_file) {
coutln "Copying ",f1," to ",f2;
j=size;
while (cnt) {
if (cnt>COPY_BUF_BLKS) {
n=COPY_BUF_BLKS;
i=n<<BLK_SIZE_BITS;
} else {
n=cnt;
i=j;
}
FRBlks(in_file, buf,LTFB_NEXT_BLK,n);
xsum^=ArcCheckSum(buf,i);
FWBlks(out_file,buf,LTFB_NEXT_BLK,n);
cnt-=n;
j-=n<<BLK_SIZE_BITS;
}
if (in_file->de.xsum &&
in_file->de.xsum!=xsum)
throw(EXCEPT_ARC_XSUM);
out_file->de.xsum=xsum;
out_file->flags|=LTF_USE_OLD_DATETIME;
out_file->de.datetime=in_file->de.datetime;
out_file->de.size=size;
out_file->de.expanded_size=in_file->de.expanded_size;
out_file->de.attr=FileAttr(f2,in_file->de.attr);
FClose(out_file);
FClose(in_file);
Free(buf);
return TRUE;
} else PutSysTextErr("ST_FILE_NOT_FOUND");
FClose(in_file);
} else PutSysTextErr("ST_FILE_NOT_FOUND");
Free(buf);
return FALSE;
}
BoolU8 MkDir(I1 *filename)
{
U8 c,size,cur_dir_cluster;
U1 *buf;
BoolU4 result=FALSE;
LTDirEntry *dLT;
I1 *name;
if (FindFile(filename,NULL,TRUE))
return FALSE;
LTFileAccess *fa=NewLTFileAccess(filename);
if (fa) {
if (*fa->mask) {
if (!CheckFileName(fa->mask))
PutSysTextErr("ST_INVALID_FILENAME");
else {
coutln "Make Directory:",filename;
name=MStrUtil(fa->mask,
SU_REMOVE_LEADING|SU_REMOVE_TRAILING|
SU_DISCARD_PARITY|SU_REMOVE_CTRL_CHARS);
size=fa->p->spc<<BLK_SIZE_BITS;
buf=MAllocZ(size);
cur_dir_cluster=NameToDirCluster(fa->p,Fs->cur_dir,TRUE);
if (fa->p->type==PT_LT) {
dLT=buf-offset(LTDirEntry.start);
c=WriteFile(name,buf,size,0,LT_ATTR_DIR,FALSE);
dLT->attr=LT_ATTR_DIR|LT_ATTR_CONTIGUOUS;
StrCpy(dLT->name,name);
dLT->cluster=c;
dLT->size=size;
dLT->expanded_size=size;
dLT->datetime=GetCurTimeLTDate;
dLT+=LT_DIR_ENTRY_SIZE;
dLT->attr=LT_ATTR_DIR|LT_ATTR_CONTIGUOUS;
dLT->name[0]='.';
dLT->name[1]='.';
dLT->name[2]=0;
dLT->cluster=cur_dir_cluster;
dLT->size=0;
dLT->expanded_size=0;
dLT->datetime=GetCurTimeLTDate;
}
WClusters(fa->p,buf,c,1,TRUE);
Free(buf);
Free(name);
result=TRUE;
}
}
DelLTFileAccess(fa);
}
return result;
}
void SysDel(I1 *wild,BoolU4 make_mask) //this is dangerous
{
LTFileAccess *fa=NewLTFileAccess(wild,make_mask);
if (fa) {
if (fa->p->type==PT_LT)
DelLTFiles(fa->p,Fs->cur_dir,fa->mask,TRUE);
DelLTFileAccess(fa);
}
}
void Format(I8 drive_letter,BoolU4 quick=TRUE,BoolU4 confirm=TRUE,U8 type=PT_LT)
{
LTPartition *p=DriveToPartition(drive_letter);
if (confirm) {
if (!AreYouSure)
return;
}
if (!p) {
PutSysTextErr("ST_INVALID_DRIVE");
return;
}
if (type==PT_LT) {
Drive(drive_letter);
FormatLT(drive_letter,quick);
InvalidateDiskCache(DriveToPartition(drive_letter),TRUE);
Drive(drive_letter);
}
}
void ReadCDImage(I1 drive,I1 *out_name)
{
LTBlkDev *bdev=DriveToBlkDev(drive);
LTPartition *p=DriveToPartition(drive);
U1 *buf=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
I1 *out_name2=DefaultExtension(out_name,"ISO");
LTFile *f=FOpen(out_name2,"w");
U8 n,dv,blk=0,cnt;
InitBlkDev(bdev,TRUE);
if (bdev->type!=LTBDT_ATAPI)
throw(EXCEPT_BLKDEV,3);
if (!out_name)
out_name=default_iso_name;
dv=bdev->blk_size>>BLK_SIZE_BITS;
cnt=((p->size+dv-1)/dv)*dv;
while (cnt) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>bdev->max_reads)
n=bdev->max_reads;
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SOUND],0))
Sound(bdev->read_freq);
ATAPIReadBlks2(bdev,buf,blk/dv,n/dv);
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SOUND],0))
Sound(0);
FWBlks(f,buf,blk,n);
cnt-=n;
blk+=n;
disk_reads+=n;
}
FClose(f);
Free(buf);
Free(out_name2);
}
class LTDuelBuf
{
U1 *buf0,*buf1;
U8 in_buf,out_buf,cnt;
I1 *filename;
LTBlkDev *CD_bdev;
};
void WriteCDImageTsk()
{
LTDuelBuf *d=Fs->user_data0;
U1 *buf;
U8 n,blk=0,cnt=d->cnt;
LTFile *f;
Preempt(ON);
InitLocalTask; //needed for disk access
if (FileAttr(d->filename)&LT_ATTR_CONTIGUOUS)
f=FOpen(d->filename,"rc");
else
f=FOpen(d->filename,"r");
while (cnt) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>d->CD_bdev->max_writes)
n=d->CD_bdev->max_writes;
buf=(d->in_buf & 1) ? d->buf1:d->buf0;
while (d->in_buf>d->out_buf+1)
SwapInNext;
FRBlks(f,buf,blk,n);
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SOUND],0))
Sound(d->CD_bdev->write_freq);
d->in_buf++;
cnt-=n;
blk+=n;
}
FClose(f);
}
void WriteCDImage(I1 drive,I1 *in_name)
{
LTDuelBuf *d=MAllocZ(sizeof(LTDuelBuf));
U1 *buf;
I1 *in_name2,*in_name3;
U8 n,dv,blk=0,cnt;
LTPartition *p=DriveToPartition(drive);
LTBlkDev *bdev=p->bdev,*bdev2;
TssStruct *tss;
BoolU4 old_preempt;
LTFile *f;
if (!in_name)
in_name=default_iso_name;
in_name3=DefaultExtension(in_name,"ISO");
in_name2=AbsoluteFileName(in_name3);
f=FOpen(in_name2,"r");
if (!f) {
Free(d);
return;
}
cnt=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS;
FClose(f);
if (bdev->type!=LTBDT_ATAPI)
throw(EXCEPT_BLKDEV,4);
bdev2=DriveToBlkDev(*in_name2);
if (bdev->irq==bdev2->irq) {
coutln "Cannot Burn CD on same IDE controller as File.\r\n";
throw(EXCEPT_BLKDEV,5);
}
bdev->flags|=LTBDF_READ_ONLY_OVERRIDE;
InitBlkDev(bdev,TRUE);
dv=bdev->blk_size>>BLK_SIZE_BITS;
if (p->size<cnt)
p->size=cnt;
d->filename=in_name2;
d->CD_bdev=bdev;
d->buf0=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
d->buf1=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
d->cnt=cnt;
old_preempt=Preempt(OFF);
tss=Spawn(&WriteCDImageTsk,"WRITE CD");
tss->user_data0=d;
while (d->in_buf<=d->out_buf)
SwapInNext;
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SOUND],0))
Sound(bdev->write_freq);
IDEWaitForDrive(bdev);
ATAPIWaitReady(bdev);
while (cnt) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>bdev->max_writes)
n=bdev->max_writes;
buf=(d->out_buf&1) ? d->buf1:d->buf0;
while (d->in_buf<=d->out_buf)
SwapInNext;
ATAPIWriteBlks(bdev,buf,blk/dv,(n+dv-1)/dv);
d->out_buf++;
cnt-=n;
blk+=n;
disk_writes+=n;
}
ATAPISync(bdev);
ATAPIClose(bdev);
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SOUND],0))
Sound(0);
bdev->flags&=~LTBDF_READ_ONLY_OVERRIDE;
LBtr(&sema_irq_busy[bdev->irq],0);
Free(d->buf0);
Free(d->buf1);
Free(d);
Free(in_name2);
Free(in_name3);
Preempt(old_preempt);
}
+599
View File
@@ -0,0 +1,599 @@
//The following definitions were copied from Linux source code
/* ATA/ATAPI Cmds pre T13 Spec */
#define WIN_NOP 0x00
#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */
#define WIN_SRST 0x08 /* ATAPI soft reset cmd */
#define WIN_DEV_RESET 0x08
#define WIN_RESTORE 0x10
#define WIN_READ 0x20 /* 28-Bit */
#define WIN_READ_EXT 0x24 /* 48-Bit */
#define WIN_READDMA_EXT 0x25 /* 48-Bit */
#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */
#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */
#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */
#define WIN_WRITE 0x30 /* 28-Bit */
#define WIN_WRITE_EXT 0x34 /* 48-Bit */
#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */
#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */
#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */
#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */
#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */
#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */
#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */
#define WIN_VERIFY_EXT 0x42 /* 48-Bit */
#define WIN_FORMAT 0x50
#define WIN_INIT 0x60
#define WIN_SEEK 0x70
#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */
#define WIN_DIAGNOSE 0x90
#define WIN_SPECIFY 0x91 /* set Drive geometry translation */
#define WIN_DOWNLOAD_MICROCODE 0x92
#define WIN_STANDBYNOW2 0x94
#define WIN_SETIDLE2 0x97
#define WIN_CHECKPOWERMODE2 0x98
#define WIN_SLEEPNOW2 0x99
#define WIN_PACKETCMD 0xA0 /* Send a packet cmd. */
#define WIN_PIDENTIFY 0xA1 /* IDEntify ATAPI dev */
#define WIN_QUEUED_SERVICE 0xA2
#define WIN_SMART 0xB0 /* self-monitoring and reporting */
#define CFA_ERASE_SECTORS 0xC0
#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/
#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */
#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */
#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */
#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */
#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */
#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */
#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */
#define WIN_GETMEDIASTATUS 0xDA
#define WIN_DOORLOCK 0xDE /* lock door ON removable drives */
#define WIN_DOORUNLOCK 0xDF /* unlock door ON removable drives */
#define WIN_STANDBYNOW1 0xE0
#define WIN_IDLEIMMEDIATE 0xE1 /* force Drive to become "ready" */
#define WIN_STANDBY 0xE2 /* Set dev in Standby Mode */
#define WIN_SETIDLE1 0xE3
#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */
#define WIN_CHECKPOWERMODE1 0xE5
#define WIN_SLEEPNOW1 0xE6
#define WIN_FLUSH_CACHE 0xE7
#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */
#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */
#define WIN_IDENTIFY 0xEC /* ask Drive to IDEntify itself */
#define WIN_MEDIAELTECT 0xED
#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */
#define WIN_SETFEATURES 0xEF /* set special Drive features */
#define EXAU1_ENABLE_NEST 0xF0
#define WIN_SECURITY_SET_PASS 0xF1
#define WIN_SECURITY_UNLOCK 0xF2
#define WIN_SECURITY_ERASE_PREPARE 0xF3
#define WIN_SECURITY_ERASE_UNIT 0xF4
#define WIN_SECURITY_FREEZE_LOCK 0xF5
#define WIN_SECURITY_DISABLE 0xF6
#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */
#define WIN_SET_MAX 0xF9
#define DISABLE_SEAGATE 0xFB
/* Bits of HD_STATUS */
#define ERR_STAT 0x01
#define INDEX_STAT 0x02
#define ECC_STAT 0x04 /* Corrected error */
#define DRQ_STAT 0x08
#define SEEK_STAT 0x10
#define WRERR_STAT 0x20
#define READY_STAT 0x40
#define BUSY_STAT 0x80
#define BAD_R_STAT (BUSY_STAT | ERR_STAT)
#define BAD_W_STAT (BAD_R_STAT | WRERR_STAT)
#define BAD_STAT (BAD_R_STAT | DRQ_STAT)
#define DRIVE_READY (READY_STAT | SEEK_STAT)
#define DATA_READY (DRQ_STAT)
#define IDE_DATA_REG 0
#define IDE_FEATURE_REG 1
#define IDE_NSECTOR_REG 2
#define IDE_SECTOR_REG 3
#define IDE_LCYL_REG 4
#define IDE_HCYL_REG 5
#define IDE_SELECT_REG 6
#define IDE_STATUS 7
#define IDE_CMD 7
#define IDE_CONTROL_REG 0
void Irq0BHandler()
{
// LBts(&sema_irqs[11],0);
}
void Irq0EHandler()
{
// LBts(&sema_irqs[14],0);
}
void Irq0FHandler()
{
// LBts(&sema_irqs[15],0);
}
void ATASelectBlk28(LTBlkDev *bdev,U8 blk,U8 cnt)
{
OutP(bdev->base1+IDE_CONTROL_REG,0x8);
OutP(bdev->base0+IDE_SECTOR_REG,blk);
OutP(bdev->base0+IDE_NSECTOR_REG,cnt);
OutP(bdev->base0+IDE_LCYL_REG,blk.u1[1]);
OutP(bdev->base0+IDE_HCYL_REG,blk.u1[2]);
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4|blk.u1[3]);
}
U8 ATAGetBlkNum28(LTBlkDev *bdev)
{
U8 result=0;
result.u1[0]=InP(bdev->base0+IDE_SECTOR_REG);
result.u1[1]=InP(bdev->base0+IDE_LCYL_REG);
result.u1[2]=InP(bdev->base0+IDE_HCYL_REG);
result.u1[3]=InP(bdev->base0+IDE_SELECT_REG) & 0xF;
return result;
}
void ATASelectBlk48(LTBlkDev *bdev,U8 blk,U8 cnt)
{//Untested
OutP(bdev->base1+IDE_CONTROL_REG,0x8);
OutP(bdev->base0+IDE_NSECTOR_REG,cnt.u1[1]);
OutP(bdev->base0+IDE_SECTOR_REG,blk.u1[3]);
OutP(bdev->base0+IDE_LCYL_REG,blk.u1[4]);
OutP(bdev->base0+IDE_HCYL_REG,blk.u1[5]);
OutP(bdev->base0+IDE_NSECTOR_REG,cnt);
OutP(bdev->base0+IDE_SECTOR_REG,blk);
OutP(bdev->base0+IDE_LCYL_REG,blk.u1[1]);
OutP(bdev->base0+IDE_HCYL_REG,blk.u1[2]);
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
}
void IDEWaitNotBusy(LTBlkDev *bdev)
{
while (InP(bdev->base0+IDE_STATUS) & BUSY_STAT)
SwapInNext;
}
void ATANop(LTBlkDev *bdev)
{
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
OutP(bdev->base0+IDE_FEATURE_REG,0);
OutP(bdev->base0+IDE_CMD,WIN_NOP);
IDEWaitNotBusy(bdev);
}
void ATACmd(LTBlkDev *bdev,U1 cmd)
{
OutP(bdev->base0+IDE_FEATURE_REG,0);
OutP(bdev->base0+IDE_CMD,cmd);
bdev->last_jiffy=Jiffies;
}
/*******
U8 ATAPIStat(LTBlkDev *bdev)
{
return InP(bdev->base0+IDE_STATUS)+
256*(InP(bdev->base0+IDE_NSECTOR_REG)+
256* InP(bdev->base0+IDE_FEATURE_REG) );
}
**********/
void ATAPIWritePktWord(LTBlkDev *bdev,U2 w)
{
while (!(InP(bdev->base0+IDE_STATUS)&DATA_READY))
SwapInNext;
OutPW(bdev->base0+IDE_DATA_REG,w.u1[1]+256*w.u1[0]);
bdev->last_jiffy=Jiffies;
}
void IDEWaitForDrive(LTBlkDev *bdev)
{
while (LBts(&sema_irq_busy[bdev->irq],0))
SwapInNext;
LBtr(&sema_irqs[bdev->irq],0);
}
/********
void IDEWaitForIrq(LTBlkDev *bdev)
{
BoolU4 old_flags=GetFlags;
Sti;
while (!LBtr(&sema_irqs[bdev->irq],0))
SwapInNext;
SetFlags(old_flags);
}
*********/
void ATAPISetMaxSpeed(LTBlkDev *bdev)
{
OutP(bdev->base1+IDE_CONTROL_REG,0x8);
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size);
OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]);
ATACmd(bdev,WIN_PACKETCMD);
ATAPIWritePktWord(bdev,0xBB00); //Set speed
ATAPIWritePktWord(bdev,0xFFFF); //read at max
ATAPIWritePktWord(bdev,0xFFFF); //write at max
ATAPIWritePktWord(bdev,0);
ATAPIWritePktWord(bdev,0);
ATAPIWritePktWord(bdev,0);
IDEWaitNotBusy(bdev);
}
void ATAPISeek(LTBlkDev *bdev,U8 blk)
{
OutP(bdev->base1+IDE_CONTROL_REG,0x8);
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size);
OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]);
ATACmd(bdev,WIN_PACKETCMD);
ATAPIWritePktWord(bdev,0x2B00); //Seek
ATAPIWritePktWord(bdev,blk>>16);
ATAPIWritePktWord(bdev,blk);
ATAPIWritePktWord(bdev,0);
ATAPIWritePktWord(bdev,0);
ATAPIWritePktWord(bdev,0x0000);
IDEWaitNotBusy(bdev);
}
void ATAPIStartStop(LTBlkDev *bdev,BoolU4 start)
{
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
ATACmd(bdev,WIN_PACKETCMD);
ATAPIWritePktWord(bdev,0x1B00); //Start/Stop
ATAPIWritePktWord(bdev,0x0000);
if (start)
ATAPIWritePktWord(bdev,0x0100);
else
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
IDEWaitNotBusy(bdev);
}
void IDEInit(LTBlkDev *bdev,BoolU4 unlock)
{
CheckLTBlkDev(bdev);
if (unlock)
IDEWaitForDrive(bdev);
LBtr(&sema_irqs[bdev->irq],0);
if (!(bdev->flags & LTBDF_HAS_BEEN_RESET)) {
OutP(bdev->base1+IDE_CONTROL_REG,0x8);
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
ATACmd(bdev,WIN_DEV_RESET);
IDEWaitNotBusy(bdev);
bdev->flags=bdev->flags | LTBDF_HAS_BEEN_RESET;
}
OutP(bdev->base1+IDE_CONTROL_REG,0x8);
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
ATACmd(bdev,WIN_READ_NATIVE_MAX);
IDEWaitNotBusy(bdev);
bdev->max_blk=ATAGetBlkNum28(bdev);
ATASelectBlk28(bdev,bdev->max_blk,0);
ATACmd(bdev,WIN_SET_MAX);
IDEWaitNotBusy(bdev);
if (bdev->type==LTBDT_ATAPI) {
ATAPIStartStop(bdev,TRUE);
ATAPISetMaxSpeed(bdev);
}
LBtr(&sema_irqs[bdev->irq],0);
if (unlock)
LBtr(&sema_irq_busy[bdev->irq],0);
}
/**********
void IDEWaitReady(LTBlkDev *bdev)
{
U8 i=0;
while (!(InP(bdev->base0+IDE_STATUS) & READY_STAT)) {
if (!(++i & 0xFFF))
IDEInit(bdev,FALSE);
ATANop(bdev);
SwapInNext;
}
}
***********/
void ATAPIWaitReady(LTBlkDev *bdev)
{
U8 pass=0;
BoolU4 cont;
do {
IDEWaitNotBusy(bdev);
if (pass)
SwapInNext;
ATANop(bdev);
if (InP(bdev->base0+IDE_STATUS) & READY_STAT) {
if (!bdev->last_jiffy || pass>16 ||
(Jiffies>bdev->last_jiffy+JIFFY_FREQ<<1)) {
ATAPIStartStop(bdev,TRUE);
}
cont=FALSE;
} else {
if (pass>16)
IDEInit(bdev,FALSE);
cont=TRUE;
}
pass++;
} while (cont || InP(bdev->base0+IDE_FEATURE_REG));
}
void ATAReadBlks2(LTBlkDev *bdev,U1 *buf, U8 cnt)
{
U8 U2s_avail,sectors_avail;
while (cnt) {
while (!(InP(bdev->base0+IDE_STATUS) & DATA_READY))
SwapInNext;
sectors_avail=1;
U2s_avail=sectors_avail<<BLK_SIZE_BITS>>1;
RepInSW(buf,U2s_avail,bdev->base0+IDE_DATA_REG);
buf+=U2s_avail<<1;
cnt-=sectors_avail;
}
IDEWaitNotBusy(bdev);
LBtr(&sema_irqs[bdev->irq],0);
}
/***********
void ATAReadBlksExt(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt)
{// Untested
IDEWaitForDrive(bdev);
ATASelectBlk48(bdev,blk,0,cnt);
ATACmd(bdev,WIN_MULTREAD_EXT);
ATAReadBlks2(bdev,buf,cnt);
LBtr(&sema_irq_busy[bdev->irq],0);
}
*************/
void ATAReadBlks(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt)
{
IDEWaitForDrive(bdev);
while ((InP(bdev->base0+IDE_STATUS) & DATA_READY))
SwapInNext;
ATASelectBlk28(bdev,blk,cnt);
ATACmd(bdev,WIN_MULTREAD);
ATAReadBlks2(bdev,buf,cnt);
LBtr(&sema_irq_busy[bdev->irq],0);
}
I8 IDEProbe(I8 base0,I8 base1,I8 unit)
{
nounusedwarn base1;
I8 timeout=0;
OutP(base0+IDE_SELECT_REG,0xE0|unit<<4);
OutP(base0+IDE_CMD,WIN_NOP);
while (InP(base0+IDE_STATUS) & BUSY_STAT) {
if (timeout++>5000)
return LTBDT_NULL;
PortNop;
}
if (timeout)
return LTBDT_ATA;
else
return LTBDT_NULL;
}
void ATAPIReadBlks2(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt)
{
U8 U2s_avail;
U1 *done_add=buf+cnt*bdev->blk_size;
if (!cnt)
return;
IDEWaitForDrive(bdev);
while ((InP(bdev->base0+IDE_STATUS) & DATA_READY))
SwapInNext;
ATAPIWaitReady(bdev);
OutP(bdev->base1+IDE_CONTROL_REG,0x8);
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size);
OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]);
ATACmd(bdev,WIN_PACKETCMD);
ATAPIWritePktWord(bdev,0xA800);
ATAPIWritePktWord(bdev,blk.u2[1]);
ATAPIWritePktWord(bdev,blk);
ATAPIWritePktWord(bdev,cnt.u2[1]);
ATAPIWritePktWord(bdev,cnt);
ATAPIWritePktWord(bdev,0x0000);
while (buf<done_add) {
while (!(InP(bdev->base0+IDE_STATUS) & DATA_READY))
SwapInNext;
if (U2s_avail=(InP(bdev->base0+IDE_HCYL_REG)<<8+InP(bdev->base0+IDE_LCYL_REG))>>1) {
if (buf+U2s_avail<<1>done_add)
U2s_avail=(done_add-buf)>>1;
RepInSW(buf,U2s_avail,bdev->base0+IDE_DATA_REG);
buf+=U2s_avail<<1;
}
}
IDEWaitNotBusy(bdev);
// ATAPIStartStop(bdev,FALSE);
LBtr(&sema_irq_busy[bdev->irq],0);
}
void ATAPIReadBlks(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt)
{
LTPartition *p=DriveToPartition(bdev->partition_base);
U8 dv=bdev->blk_size>>BLK_SIZE_BITS,n,blk2,
l2=bdev->max_reads<<1+dv<<1;
U1 *cd_buf=MAlloc(l2<<BLK_SIZE_BITS);
if (cnt) {
if (blk<=bdev->max_reads)
blk2=0;
else
blk2=((blk-bdev->max_reads)/dv)*dv;
if (blk2+l2>p->size)
l2=p->size-blk2;
n=(l2+dv-1)/dv;
ATAPIReadBlks2(bdev,cd_buf,blk2/dv,n);
if (bdev->flags & LTBDF_READ_CACHE)
LTDCAdd(p,cd_buf,blk2,n*dv);
MemCpy(buf,cd_buf+(blk-blk2)<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS);
}
Free(cd_buf);
}
void IDERBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt)
{
U8 n;
LTBlkDev *bdev=p->bdev;
CheckLTBlkDev(bdev);
while (cnt>0) {
n=cnt;
if (n>bdev->max_reads)
n=bdev->max_reads;
if (bdev->type==LTBDT_ATAPI)
ATAPIReadBlks(bdev,buf,blk,n);
else
ATAReadBlks(bdev,buf,blk,n);
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
}
}
//This is for low level disk access
//Call WBlks() instead
void ATAWriteBlks(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt)
{
U8 i,U2s_avail,sectors_avail;
IDEWaitForDrive(bdev);
ATASelectBlk28(bdev,blk,cnt);
ATACmd(bdev,WIN_MULTWRITE);
while (cnt) {
do {
i=InP(bdev->base0+IDE_STATUS);
if (i & DRIVE_READY!=DRIVE_READY ||
!(i & DATA_READY)) {
SwapInNext;
} else
break;
} while (TRUE);
//TODO
sectors_avail=1;
U2s_avail=sectors_avail<<BLK_SIZE_BITS>>1;
RepOutSW(buf,U2s_avail,bdev->base0+IDE_DATA_REG);
buf+=U2s_avail<<1;
cnt-=sectors_avail;
}
IDEWaitNotBusy(bdev);
LBtr(&sema_irq_busy[bdev->irq],0);
}
void ATAPISync(LTBlkDev *bdev)
{
IDEWaitNotBusy(bdev);
OutP(bdev->base1+IDE_CONTROL_REG,0x8);
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size);
OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]);
ATACmd(bdev,WIN_PACKETCMD);
ATAPIWritePktWord(bdev,0x3500); //Sync
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
IDEWaitNotBusy(bdev);
}
void ATAPIClose(LTBlkDev *bdev)
{
OutP(bdev->base1+IDE_CONTROL_REG,0x8);
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size);
OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]);
ATACmd(bdev,WIN_PACKETCMD);
ATAPIWritePktWord(bdev,0x5B00); //Close
ATAPIWritePktWord(bdev,0x0200);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
IDEWaitNotBusy(bdev);
}
void ATAPIWriteBlks(LTBlkDev *bdev,U1 *buf, U8 blk, U8 cnt)
{
U8 U2s_avail;
U1 *buf2;
IDEWaitNotBusy(bdev);
ATAPISeek(bdev,blk);
OutP(bdev->base0+IDE_FEATURE_REG,0);
OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size);
OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]);
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
OutP(bdev->base0+IDE_CMD,WIN_PACKETCMD);
ATAPIWritePktWord(bdev,0x0400); //FMT
ATAPIWritePktWord(bdev,blk.u2[1]);
ATAPIWritePktWord(bdev,blk);
ATAPIWritePktWord(bdev,cnt.u2[1]);
ATAPIWritePktWord(bdev,cnt);
ATAPIWritePktWord(bdev,0x0000);
IDEWaitNotBusy(bdev);
ATAPISeek(bdev,blk);
OutP(bdev->base1+IDE_CONTROL_REG,0x8);
OutP(bdev->base0+IDE_SELECT_REG,0xE0|bdev->unit<<4);
OutP(bdev->base0+IDE_LCYL_REG,bdev->blk_size);
OutP(bdev->base0+IDE_HCYL_REG,bdev->blk_size.u1[1]);
ATACmd(bdev,WIN_PACKETCMD);
ATAPIWritePktWord(bdev,0xAA00); //Write
ATAPIWritePktWord(bdev,blk.u2[1]);
ATAPIWritePktWord(bdev,blk);
ATAPIWritePktWord(bdev,cnt.u2[1]);
ATAPIWritePktWord(bdev,cnt);
ATAPIWritePktWord(bdev,0x0000);
buf2=buf+bdev->blk_size*cnt;
while (buf<buf2) {
while (!(InP(bdev->base0+IDE_STATUS) & DATA_READY))
SwapInNext;
U2s_avail=(InP(bdev->base0+IDE_HCYL_REG)<<8+InP(bdev->base0+IDE_LCYL_REG))>>1;
if (buf+U2s_avail<<1>buf2)
U2s_avail=(buf2-buf)>>1;
if (U2s_avail) {
RepOutSW(buf,U2s_avail,bdev->base0+IDE_DATA_REG);
buf+=U2s_avail<<1;
}
}
}
//TODO: needs to be fixed so it does more than one blk at
//a time when it calls ATAWriteBlks.
void IDEWBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt)
{
U8 n,dv;
LTBlkDev *bdev=p->bdev;
CheckLTBlkDev(bdev);
dv=bdev->blk_size>>BLK_SIZE_BITS;
if (bdev->type==LTBDT_ATAPI) {
IDEWaitForDrive(bdev);
ATAPIWaitReady(bdev);
}
while (cnt>0) {
n=cnt;
if (n>bdev->max_writes)
n=bdev->max_writes;
if (bdev->type==LTBDT_ATAPI)
ATAPIWriteBlks(bdev,buf,blk/dv,(n+dv-1)/dv);
else
ATAWriteBlks(bdev,buf,blk,n);
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
}
if (bdev->type==LTBDT_ATAPI) {
ATAPISync(bdev);
// ATAPIStartStop(bdev,FALSE);
LBtr(&sema_irq_busy[bdev->irq],0);
}
}
+500
View File
@@ -0,0 +1,500 @@
U8 AddBlkDev(LTBlkDev *bd,BoolU4 one_partition)
{
I8 i,j,ext_base,num_partition;
U8 offset;
LTPartition *p;
I1 *drname;
LTBootStruct br;
MasterBootStruct mbr;
bd->ch_L='L';
bd->ch_B='B';
bd->ch_D='D';
num_partition=bd->partition_base-'A';
p=&local_partitions[num_partition];
MemSet(p,0,sizeof(LTPartition));
p->drive=num_partition+'A';
p->ch_L='L';
p->ch_P='P';
p->ch_E='E';
p->bdev=bd;
p->size=bd->max_blk+1;
j=(sys_boot_code.u1[1]==0xE0) ? 0:1;
switch (sys_boot_code.u1[0]) {
case BOOT_CODE_CDROM:
if (sys_boot_code.u2[1]==bd->base0 && j==bd->unit)
boot_blkdev=bd;
break;
case BOOT_CODE_HARDDRIVE:
if (sys_boot_code.u2[1]==bd->base0 && j==bd->unit)
boot_blkdev=bd;
break;
}
if (boot_blkdev==bd)
bd->flags|=LTBDF_HAS_BEEN_RESET;
switch (bd->type) {
case LTBDT_FDC:
p->type=PT_LT;
p->RBlks=&FDCRBlks;
p->WBlks=&FDCWBlks;
num_partition++;
break;
case LTBDT_RAM:
p->type=PT_LT;
p->RBlks=&RAMRBlks;
p->WBlks=&RAMWBlks;
num_partition++;
break;
case LTBDT_ATA:
InitBlkDev(bd,TRUE);
offset=0;
ext_base=INVALID_CLUSTER;
if (one_partition) {
p->type=PT_LT;
p->RBlks=&IDERBlks;
p->WBlks=&IDEWBlks;
p->size=bd->max_blk+1;
num_partition++;
//The following read is a test read.
//if it hangs, the drive is not supported.
ATAReadBlks(bd,&mbr,offset,1);
break;
}
while (TRUE) {
ATAReadBlks(bd,&mbr,offset,1);
if (mbr.signature!=0xAA55)
break;
j=-1;
for (i=0;i<4;i++) {
if (mbr.p[i].type!=0) {
p=&local_partitions[num_partition];
MemSet(p,0,sizeof(LTPartition));
p->drive=num_partition+'A';
p->ch_L='L';
p->ch_P='P';
p->ch_E='E';
p->bdev=bd;
p->RBlks=&IDERBlks;
p->WBlks=&IDEWBlks;
p->offset=mbr.p[i].offset+offset;
p->size =mbr.p[i].size;
p->type =mbr.p[i].type;
if (p->type==PT_LT)
InitLTPartition(p,TRUE);
else {
if (p->type==PT_FAT32+1) p->type=PT_FAT32;
if (p->type==PT_FAT32) {
ATAReadBlks(bd,&br,p->offset,1);
if (br.signature==PT_LT)
InitLTPartition(p,TRUE);
}
}
if (p->type==5 || p->type==0xF)
j=i;
else
num_partition++;
}
}
if (j<0)
break;
if (mbr.p[j].offset==0)
break;
if (ext_base==INVALID_CLUSTER) {
offset=mbr.p[j].offset;
ext_base=offset;
} else
offset=mbr.p[j].offset+ext_base;
}
break;
case LTBDT_ATAPI:
p->type=PT_ISO9660;
p->RBlks=&IDERBlks;
p->WBlks=&IDEWBlks;
p->size =CD_FILE_OFFSET;
num_partition++;
break;
case LTBDT_LT_FILE:
drname=ChangeExtension(bd->filename,"DVC");
bd->filename=ANewStr(drname);
Free(drname);
p->type=PT_LT;
p->RBlks=&FileRBlks;
p->WBlks=&FileWBlks;
num_partition++;
break;
case LTBDT_NON_LT_FILE:
p->type=PT_LT;
p->offset=bd->non_lt_offset;
p->RBlks=&NonLTFileRBlks;
p->WBlks=&NonLTFileWBlks;
if (bd->flags & LTBDF_FORMAT)
p->size=bd->max_blk-bd->min_blk+1;
num_partition++;
break;
}
return num_partition-(bd->partition_base-'A');
}
void HintATA()
{
void *base_PCI=0xF0000000;
void *base;
U4 *dd,d1,d2;
U1 *bb,d3;
U2 *ww;
base=base_PCI+0xF9000;
ww=base;
if (*ww==0x8086) {
dd=base+0x10;
d1=*dd;
dd=base+0x14;
d2=*dd;
bb=base+0x3C;
d3=*bb;
if (d1&1 && d2&1) {
if (IDEProbe(d1&-8,d2&-4,0))
coutln "$$FG,PURPLE$$Primary IDE$$FG$$\r\nBase0: 0x",d1&-8,"\r\nBase1: 0x",d2&-4,"\r\nIrq: 0x",d3," Unit 0";
if (IDEProbe(d1&-8,d2&-4,1))
coutln "$$FG,PURPLE$$Primary IDE$$FG$$\r\nBase0: 0x",d1&-8,"\r\nBase1: 0x",d2&-4,"\r\nIrq: 0x",d3," Unit 1";
}
dd=base+0x18;
d1=*dd;
dd=base+0x1C;
d2=*dd;
if (d1&1 && d2&1) {
if (IDEProbe(d1&-8,d2&-4,0))
coutln "$$FG,PURPLE$$Secondary IDE$$FG$$\r\nBase0: 0x",d1&-8,"\r\nBase1: 0x",d2&-4,"\r\nIrq: 0x",d3," Unit 0";
if (IDEProbe(d1&-8,d2&-4,1))
coutln "$$FG,PURPLE$$Secondary IDE$$FG$$\r\nBase0: 0x",d1&-8,"\r\nBase1: 0x",d2&-4,"\r\nIrq: 0x",d3," Unit 1";
}
} else {
d1=0x1F0;
d2=0x3F6;
d3=14;
if (IDEProbe(d1,d2,0))
coutln "$$FG,PURPLE$$Primary IDE$$FG$$\r\nBase0: 0x",d1,"\r\nBase1: 0x",d2,"\r\nIrq: 0x",d3," Unit 0";
if (IDEProbe(d1,d2,1))
coutln "$$FG,PURPLE$$Primary IDE$$FG$$\r\nBase0: 0x",d1,"\r\nBase1: 0x",d2,"\r\nIrq: 0x",d3," Unit 1";
d1=0x170;
d2=0x376;
d3=15;
if (IDEProbe(d1,d2,0))
coutln "$$FG,PURPLE$$Secondary IDE$$FG$$\r\nBase0: 0x",d1,"\r\nBase1: 0x",d2,"\r\nIrq: 0x",d3," Unit 0";
if (IDEProbe(d1,d2,1))
coutln "$$FG,PURPLE$$Secondary IDE$$FG$$\r\nBase0: 0x",d1,"\r\nBase1: 0x",d2,"\r\nIrq: 0x",d3," Unit 1";
}
base=base_PCI+0xFA000;
ww=base;
if (*ww==0x8086) {
dd=base+0x10;
d1=*dd;
dd=base+0x14;
d2=*dd;
bb=base+0x3C;
d3=*bb;
if (d1&1 && d2&1) {
if (IDEProbe(d1&-8,d2&-4,0))
coutln "$$FG,PURPLE$$Primary SATA$$FG$$\r\nBase0: 0x",d1&-8,"\r\nBase1: 0x",d2&-4,"\r\nIrq: 0x",d3," Unit 0";
if (IDEProbe(d1&-8,d2&-4,1))
coutln "$$FG,PURPLE$$Primary SATA$$FG$$\r\nBase0: 0x",d1&-8,"\r\nBase1: 0x",d2&-4,"\r\nIrq: 0x",d3," Unit 1";
}
dd=base+0x18;
d1=*dd;
dd=base+0x1C;
d2=*dd;
if (d1&1 && d2&1) {
if (IDEProbe(d1&-8,d2&-4,0))
coutln "$$FG,PURPLE$$Secondary SATA$$FG$$\r\nBase0: 0x",d1&-8,"\r\nBase1: 0x",d2&-4,"\r\nIrq: 0x",d3,"Unit 0";
if (IDEProbe(d1&-8,d2&-4,1))
coutln "$$FG,PURPLE$$Secondary SATA$$FG$$\r\nBase0: 0x",d1&-8,"\r\nBase1: 0x",d2&-4,"\r\nIrq: 0x",d3,"Unit 1";
}
}
CrLf;
CrLf;
}
void AddDrives(BoolU4 repartition=FALSE)
{
LTBlkDev *bd;
I8 base_partition,drive_letter,type,k;
I1 buf[32],buf2[128],buf3[128],buf4[128];
BoolU4 format,add;
void my_PartitionDrive(I1 drive);
do {
PartitionRep;
PutSysText("ST_ADDDRIVES1");
base_partition=ToUpper(GetChar)-'A';
CrLf;
if (base_partition>=0 && base_partition<32) {
PutSysText("ST_ADDDRIVES2");
type=GetChar-'0';
CrLf;
k=0;
if (type==LTBDT_LT_FILE) {
PutSysText("ST_ADDDRIVES3");
GetS(buf2,128);
PutSysText("ST_ADDDRIVES4");
format=YorN;
*buf=0;
} else if (type==LTBDT_ATA || type==LTBDT_ATAPI) {
HintATA;
PutSysText("ST_ADDDRIVES12");
GetS(buf2,128);
PutSysText("ST_ADDDRIVES13");
GetS(buf3,128);
PutSysText("ST_ADDDRIVES14");
GetS(buf4,128);
PutSysText("ST_ADDDRIVES7");
k=GetChar-'0';
CrLf;
}
if (type==LTBDT_NON_LT_FILE) {
PutSysText("ST_ADDDRIVES15");
drive_letter=GetChar;
CrLf;
PutSysText("ST_ADDDRIVES16");
GetS(buf2,128);
}
if (type==LTBDT_RAM ||
type==LTBDT_LT_FILE && format) {
PutSysText("ST_ADDDRIVES5");
GetS(buf,32);
} else if (type==LTBDT_FDC) {
PutSysText("ST_ADDDRIVES7");
k=GetChar-'0';
CrLf;
}
if (type>LTBDT_NULL && type<=LTBDT_NON_LT_FILE &&
k>=0 && k<=1) {
bd=local_blkdevs+sizeof(LTBlkDev)*(num_blkdevs++);
bd->partition_base=base_partition+'A';
bd->unit=k;
if (type==LTBDT_FDC) {
bd->base0=0x3F0;
bd->irq=6;
} else if (type==LTBDT_ATA ||
type==LTBDT_ATAPI) {
bd->base0=AtoI(buf2);
bd->base1=AtoI(buf3);
bd->irq=AtoI(buf4);
}
if (type==LTBDT_FDC ||
type==LTBDT_ATAPI)
bd->flags=LTBDF_REMOVABLE;
else
bd->flags=0;
if (type!=LTBDT_RAM)
bd->flags|=LTBDF_READ_CACHE;
if (type==LTBDT_ATAPI) {
bd->blk_size=CD_BLK_SIZE;
bd->flags|=LTBDF_READ_ONLY;
} else
bd->blk_size=BLK_SIZE;
if (type==LTBDT_RAM ||
type==LTBDT_LT_FILE && format) {
bd->max_blk=AtoI(buf)-1;
if (bd->max_blk<fdc_max_sector)
bd->max_blk=fdc_max_sector;
} else if (type==LTBDT_FDC)
bd->max_blk=fdc_max_sector;
else
bd->max_blk=0xEFFFFFFF;
if (type==LTBDT_LT_FILE) {
bd->filename=ANewStr(buf2);
if (format)
bd->flags=bd->flags|LTBDF_FORMAT;
} else if (type==LTBDT_NON_LT_FILE) {
bd->non_lt_drive=drive_letter;
bd->non_lt_offset=AtoI(buf2);
}
bd->type=type;
add=TRUE;
if (type==LTBDT_ATA && repartition) {
if (my_PartitionDrive=FindExtern("PartitionDrive")) {
PutSysText("ST_ADDDRIVES11");
if (YorN) {
if (!AddBlkDev(bd,TRUE))
PutSysText("ST_FAILED");
else
my_PartitionDrive(bd->partition_base);
add=FALSE;
}
}
}
if (add) {
if (!AddBlkDev(bd,FALSE))
PutSysText("ST_FAILED");
}
} else
PutSysText("ST_FAILED");
}
} while (base_partition>=0 && base_partition<32);
}
void SetObtainedBaseUnit(LTBlkDev *bd)
{
if (sys_boot_code.u1[1]==0xE0)
bd->unit=0;
else
bd->unit=1;
if (sys_boot_code.u2[1]==0x1F0) {
bd->base0=0x1F0;
bd->base1=0x3F6;
bd->irq=14;
} else {
bd->base0=0x170;
bd->base1=0x376;
bd->irq=15;
}
}
void InitAllBlkDevs()
{
LTBlkDev *bd;
I8 i;
num_blkdevs=0;
boot_blkdev=NULL;
local_blkdevs=AMAllocZ(sizeof(LTBlkDev)<<5);
monitor_floppy_tss=NULL;
fdc_retries=2;
fdc_drive_heads=2;
fdc_disk_cylinders=80;
fdc_disk_sectors=18;
fdc_max_sector=fdc_drive_heads*fdc_disk_cylinders*fdc_disk_sectors-1;
fdc_dma_buf=0xD000;
ext[EXT_IRQ06]=&Irq06Handler;
ext[EXT_IRQ0B]=&Irq0BHandler;
ext[EXT_IRQ0E]=&Irq0EHandler;
ext[EXT_IRQ0F]=&Irq0FHandler;
local_partitions=AMAllocZ(sizeof(LTPartition)<<5);
for (i=0;i<32;i++)
drive_to_partition[i]=&local_partitions[i];
dc_col=0;
#exe {
I8 base_partition,type,drive_letter,k,n,num=0;
I1 buf[32],buf2[128],buf3[128],buf4[128];
BoolU4 format;
PutSysText("ST_ADDDRIVES0");
do {
PutSysText("ST_ADDDRIVES1");
base_partition=ToUpper(GetChar)-'A';
CrLf;
if (base_partition>=0 && base_partition<32) {
PutSysText("ST_ADDDRIVES2");
type=GetChar-'0';
CrLf;
k=0;
if (type==LTBDT_LT_FILE) {
PutSysText("ST_ADDDRIVES3");
GetS(buf2,128);
PutSysText("ST_ADDDRIVES4");
format=YorN;
*buf=0;
}
if (type==LTBDT_RAM ||
type==LTBDT_LT_FILE && format) {
PutSysText("ST_ADDDRIVES5");
GetS(buf,32);
} else if (type==LTBDT_ATA ||
type==LTBDT_ATAPI) {
HintATA;
if (type==LTBDT_ATAPI)
PutSysText("ST_ADDDRIVES12a");
PutSysText("ST_ADDDRIVES12");
GetS(buf2,128);
if (type!=LTBDT_ATAPI || *buf2) {
PutSysText("ST_ADDDRIVES13");
GetS(buf3,128);
PutSysText("ST_ADDDRIVES14");
GetS(buf4,128);
PutSysText("ST_ADDDRIVES7");
k=GetChar-'0';
CrLf;
}
}
if (type==LTBDT_NON_LT_FILE) {
PutSysText("ST_ADDDRIVES15");
drive_letter=GetChar;
CrLf;
PutSysText("ST_ADDDRIVES16");
GetS(buf2,128);
}
if (type>LTBDT_NULL && type<=LTBDT_NON_LT_FILE &&
k>=0 && k<=1) {
ExePrintF("bd=local_blkdevs+sizeof(LTBlkDev)*(num_blkdevs++);");
ExePrintF("bd->partition_base=%d;",
base_partition+'A');
ExePrintF("bd->unit=%d;",k);
if (type==LTBDT_FDC)
ExePrintF("bd->base0=0x3F0;bd->irq=6;");
else if (type==LTBDT_ATA || type==LTBDT_ATAPI) {
if (type==LTBDT_ATAPI && !*buf2)
ExePrintF("SetObtainedBaseUnit(bd);");
else
ExePrintF("bd->base0=%s;bd->base1=%s;bd->irq=%s;",
buf2,buf3,buf4);
}
if (type==LTBDT_FDC || type==LTBDT_ATAPI)
ExePrintF("bd->flags=LTBDF_REMOVABLE;");
else
ExePrintF("bd->flags=0;");
if (type!=LTBDT_RAM)
ExePrintF("bd->flags=bd->flags|LTBDF_READ_CACHE;");
if (type==LTBDT_ATAPI) {
ExePrintF("bd->blk_size=CD_BLK_SIZE;");
ExePrintF("bd->flags=bd->flags | LTBDF_READ_ONLY;");
} else
ExePrintF("bd->blk_size=BLK_SIZE;");
if (type==LTBDT_RAM ||
type==LTBDT_LT_FILE && format) {
n=AtoI(buf)-1;
if (n<fdc_max_sector)
n=fdc_max_sector;
ExePrintF("bd->max_blk=%d;",n);
} else if (type==LTBDT_FDC)
ExePrintF("bd->max_blk=fdc_max_sector;");
else
ExePrintF("bd->max_blk=0xEFFFFFFF;");
if (type==LTBDT_LT_FILE) {
ExePrintF("bd->filename=ANewStr(\"%s\");",buf2);
if (format)
ExePrintF("bd->flags=bd->flags|LTBDF_FORMAT;");
} else if (type==LTBDT_NON_LT_FILE) {
ExePrintF("bd->non_lt_drive=%d;",drive_letter);
n=AtoI(buf2);
ExePrintF("bd->non_lt_offset=%d;",n);
}
ExePrintF("bd->type=%d;",type);
ExePrintF("AddBlkDev(bd,FALSE);");
num++;
} else
PutSysText("ST_FAILED");
}
} while (num==0 || base_partition>=0 && base_partition<32);
ExePrintF("default_drive=\'%C\';",insboot_dst_drive);
}
PartitionRep;
}
Binary file not shown.
Binary file not shown.
+282
View File
@@ -0,0 +1,282 @@
#define FDC_p0 0
#define FDC_p1 1
#define FDC_DOR 2
#define FDC_p3 3
#define FDC_STATUS 4
#define FDC_DATA 5
#define FDC_DIR 7
#define FDC_DCR 7
void Irq06Handler()
{
LBts(&sema_irqs[6],0);
}
void FDCFlushStatus(LTBlkDev *bdev)
{
U1 b;
I8 i;
MemSet(bdev->status,0,32);
i=0;
while (i<32) {
b=InP(bdev->base0+FDC_STATUS);
if (b & 0x80) {
if (b & 0x40)
bdev->status[i++]=InP(bdev->base0+FDC_DATA);
else
break;
}
SwapInNext;
}
if (i==32)
throw(EXCEPT_FDC,2);
bdev->status[0]=bdev->status[0] & 0xC8; //clear non-error bits
bdev->last_jiffy=Jiffies;
}
void FDCWaitIrq(LTBlkDev *bdev)
{
BoolU4 old_flags=GetFlags;
Sti;
while (!LBtr(&sema_irqs[bdev->irq],0)) {
/*
if (!(InP(bdev->base0+FDC_p0) & 0x80)) //Pending IRQ?
throw(EXCEPT_FDC,1);
*/
SwapInNext;
}
SetFlags(old_flags);
FDCFlushStatus(bdev);
}
void FDCSendCmdU1(LTBlkDev *bdev,U1 v)
{
FDCFlushStatus(bdev);
OutP(bdev->base0+FDC_DATA,v);
}
void FDCSeek(LTBlkDev *bdev,U1 cyl, U1 head)
{
FDCSendCmdU1(bdev,0x0F);
FDCSendCmdU1(bdev,head<<2);
FDCSendCmdU1(bdev,cyl);
FDCWaitIrq(bdev);
}
void FDCFree(LTBlkDev *bdev)
{
LBtr(&sema_irq_busy[bdev->irq],0);
}
void MonitorFDCTsk()
{
LTBlkDev *bdev;
bdev=Fs->user_data0;
CheckLTBlkDev(bdev);
while (TRUE) {
if (!LBts(&sema_irq_busy[bdev->irq],0)) {
if (bdev->last_jiffy) {
if (Jiffies > bdev->last_jiffy+JIFFY_FREQ<<1) {
FDCSeek(bdev,0,0);
FDCSeek(bdev,0,1);
OutP(bdev->base0+FDC_DOR,0x00);
bdev->last_jiffy=0;
}
}
FDCFree(bdev);
}
SwapInNext;
}
}
void FDCGet(LTBlkDev *bdev)
{
CheckLTBlkDev(bdev);
while (LBts(&sema_irq_busy[bdev->irq],0))
SwapInNext;
LBtr(&sema_irqs[bdev->irq],0);
if (!bdev->last_jiffy) {
bdev->last_jiffy=Jiffies;
OutP(bdev->base0+FDC_DOR,0x00);
BusyWait(100);
OutP(bdev->base0+FDC_DOR,0x1C); //Motor ON
FDCWaitIrq(bdev);
OutP(bdev->base0+FDC_DCR,0x00); //step,Load, Unload specs
FDCSendCmdU1(bdev,0x03);
FDCSendCmdU1(bdev,0xCF);
FDCSendCmdU1(bdev,0x10);
FDCWaitIrq(bdev);
FDCSendCmdU1(bdev,0x07); //Recalibrate
FDCSendCmdU1(bdev,0x00);
FDCWaitIrq(bdev);
}
}
void FDCReset(LTBlkDev *bdev)
{
CheckLTBlkDev(bdev);
OutP(0x0A,0x42); //Shut down old DMA
OutP(0x09,0x02);
bdev->last_jiffy=0;
LBtr(&sema_irq_busy[bdev->irq],0);
FDCGet(bdev);
}
BoolU8 FDCReadTrack(LTBlkDev *bdev,U1 cyl, U1 head,U8 blk)
{
I8 i;
U8 size=fdc_disk_sectors<<BLK_SIZE_BITS-1;
CheckLTBlkDev(bdev);
for (i=0;i<fdc_retries;i++) {
FDCSeek(bdev,cyl,head);
OutP(0x0A,0x42); //Shut down old DMA
OutP(0x09,0x02);
OutP(0x08,0x00); //ctrl
OutP(0x0B,0x56); //mode Read
OutP(0x0C,0);
OutP(0x04,fdc_dma_buf & 0xFF); //addr
OutP(0x04,(fdc_dma_buf>>8) & 0xFF);
OutP(0x81,fdc_dma_buf>>16); //set page
OutP(0x0C,0);
OutP(0x05,size.u1[0]); //cnt
OutP(0x05,size.u1[1]);
OutP(0x0A,0x02); //Start new DMA
OutP(0x09,0x06);
FDCSendCmdU1(bdev,0x62);
FDCSendCmdU1(bdev,head<<2);
FDCSendCmdU1(bdev,cyl);
FDCSendCmdU1(bdev,head);
FDCSendCmdU1(bdev,1); //sector
FDCSendCmdU1(bdev,BLK_SIZE>>8);
FDCSendCmdU1(bdev,fdc_disk_sectors); //last sec
FDCSendCmdU1(bdev,0x1B); //gap
FDCSendCmdU1(bdev,0xFF);
FDCWaitIrq(bdev);
if (bdev->status[0] || bdev->status[1] ||
bdev->status[2]) {
PrintFErr("FDC Read:%X,%X,%X\r\n",bdev->status[2],bdev->status[1],bdev->status[0]);
FDCReset(bdev);
} else
return TRUE;
}
coutln "FDC Read Failed!!! Blk:",blk;
return FALSE;
}
BoolU8 FDCRBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt)
{
LTCacheBlk *tempc;
BoolU4 okay=TRUE;
U8 n,blk2;
U1 cyl,head,sec;
LTBlkDev *bdev=p->bdev;
CheckLTBlkDev(bdev);
while (cnt>0) {
if (bdev->flags & LTBDF_READ_CACHE) {
while (cnt) {
tempc=LTDCFindBlk(p,blk); //TODO preempt
if (tempc) {
MemCpy(buf,&tempc->body,BLK_SIZE);
cnt--;
buf+=BLK_SIZE;
blk++;
} else
break;
}
}
if (cnt) {
n=cnt;
if (n>bdev->max_reads)
n=bdev->max_reads;
blk2=blk;
sec=blk2%fdc_disk_sectors+1;blk2=blk2/fdc_disk_sectors;
head=blk2%fdc_drive_heads;
cyl=blk2/fdc_drive_heads;
if (!FDCReadTrack(bdev,cyl,head,blk-(sec-1)))
okay=FALSE;
MemCpy(buf,fdc_dma_buf+(sec-1)<<BLK_SIZE_BITS,n<<BLK_SIZE_BITS);
if (bdev->flags & LTBDF_READ_CACHE)
LTDCAdd(DriveToPartition(bdev->partition_base),
fdc_dma_buf,blk-(sec-1),fdc_disk_sectors);
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
}
}
return okay;
}
BoolU8 FDCWriteBlk2(LTBlkDev *bdev,U1 *buf, U1 cyl, U1 head,U1 sec,U8 blk)
{
I8 i;
U8 size=bdev->max_writes<<BLK_SIZE_BITS-1;
for (i=0;i<fdc_retries;i++) { //Retry up to 10 times
FDCSeek(bdev,cyl,head);
MemCpy(fdc_dma_buf,buf,size+1);
OutP(0x0A,0x42); //Shut down old DMA
OutP(0x09,0x02);
OutP(0x08,0x00); //ctrl
OutP(0x0B,0x5A); //mode Write
OutP(0x0C,0);
OutP(0x04,fdc_dma_buf & 0xFF); //addr
OutP(0x04,(fdc_dma_buf>>8) & 0xFF);
OutP(0x81,fdc_dma_buf>>16); //set page
OutP(0x0C,0);
OutP(0x05,size.u1[0]); //cnt
OutP(0x05,size.u1[1]);
OutP(0x0A,0x02); //Start new DMA
OutP(0x09,0x06);
FDCSendCmdU1(bdev,0xC5);
FDCSendCmdU1(bdev,head<<2);
FDCSendCmdU1(bdev,cyl);
FDCSendCmdU1(bdev,head);
FDCSendCmdU1(bdev,sec);
FDCSendCmdU1(bdev,BLK_SIZE>>8);
FDCSendCmdU1(bdev,fdc_disk_sectors); //last sec
FDCSendCmdU1(bdev,0x1B); //gap
FDCSendCmdU1(bdev,0xFF);
FDCWaitIrq(bdev);
if (bdev->status[2] || bdev->status[1] ||
bdev->status[0]) {
PrintFErr("FDC Write:%X,%X,%X\r\n",bdev->status[0],bdev->status[1],bdev->status[2]);
FDCReset(bdev);
} else
return TRUE;
}
coutln "FDC Write Failed!!! Blk:",blk;
return FALSE;
}
BoolU8 FDCWBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt)
{
BoolU4 okay=TRUE;
U8 n,blk2;
U1 cyl,head,sec;
LTBlkDev *bdev=p->bdev;
CheckLTBlkDev(bdev);
while (cnt>0) {
n=cnt;
if (n>bdev->max_writes)
n=bdev->max_writes;
blk2=blk;
sec=blk2%fdc_disk_sectors+1;blk2=blk2/fdc_disk_sectors;
head=blk2%fdc_drive_heads;
cyl=blk2/fdc_drive_heads;
if (!FDCWriteBlk2(bdev,buf,cyl,head,sec,blk))
okay=FALSE;
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
}
return okay;
}
Binary file not shown.
Binary file not shown.
+653
View File
@@ -0,0 +1,653 @@
void FreeLTFreeList(LTPartition *p,BoolU4 unlock)
{
LTFreeList *tempf,*tempf1;
try {
LockPartition(p);
if (tempf=p->next_free) {
while (tempf!=&p->next_free) {
tempf1=tempf->next;
AFree(tempf);
tempf=tempf1;
}
}
p->next_free=NULL;
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
}
void BuildLTFreeList(LTPartition *p,BoolU4 unlock)
{
LTFreeList *tempf;
U8 i,first=0,
max_cluster=(p->size+p->offset-p->data)/p->spc;
try {
LockPartition(p);
if (p->next_free)
FreeLTFreeList(p,FALSE);
p->next_free=&p->next_free;
p->last_free=&p->next_free;
while (first<max_cluster) {
i=0; //count free clusters
while (first+i<max_cluster) {
SetLTBuf(p,first+i);
if (Bt(p->cur_MAP_blk,(first+i)&(BLK_SIZE<<3-1)))
break;
else
i++;
}
if (i) {
tempf=AMAlloc(sizeof(LTFreeList));
tempf->size=i;
tempf->start=first;
InsQue(tempf,p->last_free);
}
first+=i+1;
}
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
}
void InitLTPartition(LTPartition *p,BoolU4 unlock)
{
LTBootStruct br;
try {
LockPartition(p);
RBlks(p,&br,p->offset,1,FALSE);
if (br.signature!=PT_LT ||
br.signature2!=0xAA55)
throw(EXCEPT_PARTITION,12);
p->type=PT_LT;
FreeLTFreeList(p,FALSE);
p->spc=br.sectors_per_cluster;
p->size=br.sectors;
p->data=p->offset+1+br.bitmap_sectors-p->spc;
p->root_cluster=br.root_cluster;
p->MAP1=p->offset+1;
p->MAP2=p->offset+1;
AllocMAPBuf(p,1);
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
}
void FormatLT(I1 drive_letter,BoolU4 quick=TRUE)
{
U1 *root_dir;
LTDirEntry *dLT;
LTBootStruct *br=MAllocZ(BLK_SIZE);
LTPartition *p=DriveToPartition(drive_letter);
U8 i,n;
try {
LockPartition(p);
// SetDriveType(drive_letter,PT_LT);
SetDriveType(drive_letter,PT_FAT32);
p->type=PT_LT;
br->U1s_per_sector=BLK_SIZE;
if (p->size<0x20000)
br->sectors_per_cluster=1;
else if (p->size<0x200000)
br->sectors_per_cluster=2;
else if (p->size<0x2000000)
br->sectors_per_cluster=4;
else if (p->size<0x20000000)
br->sectors_per_cluster=8;
else if (p->size<0x200000000)
br->sectors_per_cluster=16;
else
br->sectors_per_cluster=32;
br->signature=PT_LT;
br->signature2=0xAA55;
br->sectors=p->size;
n=br->sectors_per_cluster*(BLK_SIZE<<3);
n=(br->sectors+n-1)/n;
br->bitmap_sectors=n;
br->unique_id=BootTime;
br->root_cluster=0;
if (quick)
i=n+1;
else
i=p->size;
WZeroBlks(p,p->offset,i,FALSE);
WBlks(p,br,p->offset,1,FALSE);
InitLTPartition(p,FALSE);
AllocClusters(p,0,1,FALSE,FALSE); //Alloc #1
br->root_cluster=AllocClusters(p,0,1,FALSE,FALSE);
WBlks(p,br,p->offset,1,FALSE);
root_dir=MAllocZ(p->spc<<BLK_SIZE_BITS);
dLT=root_dir-offset(LTDirEntry.start);
dLT->attr=LT_ATTR_DIR|LT_ATTR_CONTIGUOUS;
dLT->name[0]='.';
dLT->cluster=br->root_cluster;
dLT->size=p->spc<<BLK_SIZE_BITS;
dLT->expanded_size=dLT->size;
dLT->datetime=GetCurTimeLTDate;
dLT+=LT_DIR_ENTRY_SIZE;
dLT->name[0]='.';
dLT->name[1]='.';
dLT->attr=LT_ATTR_DIR|LT_ATTR_CONTIGUOUS;
dLT->cluster=br->root_cluster;
dLT->datetime=GetCurTimeLTDate;
WBlks(p,root_dir,p->data+br->root_cluster*p->spc,p->spc,FALSE);
InitLTPartition(p,FALSE);
UnlockPartition(p);
} catch
UnlockPartition(p);
Free(br);
Free(root_dir);
}
BoolU8 FindLTFile(LTPartition *p,U8 cur_dir_cluster,I1 *name,LTDirEntry *result,
BoolU4 dir_only,BoolU4 file_only,BoolU4 unlock)
{
BoolU4 res=FALSE;
LTDirEntry *buf,*buf2,*ptr;
I1 dname[LT_MAX_FILENAME_LEN+1];
BoolU4 cont2=FALSE;
U1 ch;
MemSet(result,0,sizeof(LTDirEntry));
CheckLTPartition(p);
if (p->type!=PT_LT)
PutSysTextErr("ST_NOT_LT");
else if (!ToLTFilename(dname,name))
PutSysTextErr("ST_INVALID_FILENAME");
else {
try {
LockPartition(p);
buf2=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(p,buf2,cur_dir_cluster,1,FALSE);
ptr=buf2-offset(LTDirEntry.start);
buf=MAlloc(ptr->size);
RClusters(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS/p->spc,FALSE);
Free(buf2);
ptr=buf-offset(LTDirEntry.start);
ptr->name[0]='.';
ptr->name[1]=0;
while (TRUE) {
ch=ptr->name[0];
if (!ch)
break;
else if (!(ptr->attr & LT_ATTR_DELETED)) {
if (dir_only && !(ptr->attr & LT_ATTR_DIR))
cont2=FALSE;
else if (file_only && ptr->attr & LT_ATTR_DIR)
cont2=FALSE;
else
cont2=TRUE;
if (cont2 && !StrCmp(dname,ptr->name)) {
MemCpy(&result->attr,&ptr->attr,LT_DIR_ENTRY_SIZE);
res=TRUE;
goto exit_this;
}
}
ptr+=LT_DIR_ENTRY_SIZE;
}
exit_this:
Free(buf);
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
}
return res;
}
U1 *ReadLTFile(LTPartition *p,I1 *cur_dir,I1 *filename,U8 *size,
U8 *attr,BoolU4 raw,ArcCompressStruct **ac2)
{
U1 *buf=NULL;
LTDirEntry de;
U8 c,cluster_size=p->spc<<BLK_SIZE_BITS,cluster_cnt;
ArcCompressStruct *ac;
U8 cur_dir_cluster=NameToDirCluster(p,cur_dir,TRUE);
CheckLTPartition(p);
if (size)
*size=0;
if (ac2)
*ac2=NULL;
if (attr)
*attr=0;
if (p->type!=PT_LT)
PutSysTextErr("ST_NOT_LT");
else {
try {
LockPartition(p);
if (FindLTFile(p,cur_dir_cluster,filename,&de,FALSE,TRUE,FALSE)) {
if (attr)
*attr=de.attr;
cluster_cnt=(de.size+cluster_size-1)/cluster_size;
buf=MAlloc(cluster_cnt*cluster_size+1);
c=de.cluster;
c=RClusters(p,buf,c,cluster_cnt,FALSE,TRUE);
if (de.xsum) {
if ((de.xsum^ArcCheckSum(buf,de.size))!=LT_XSUM)
throw(EXCEPT_ARC_XSUM);
}
if ((FileAttr(de.name) & LT_ATTR_COMPRESSED) && !raw) {
ac=buf;
if (attr)
*attr=FileAttr(de.name,*attr);
if (size)
*size=ac->expanded_size;
if (ac2) {
*ac2=ac;
buf=ExpandBuf(ac);
} else {
buf=ExpandBuf(ac);
Free(ac);
}
} else {
buf[de.size]=0; //Terminate
if (size)
*size=de.size;
}
if (attr)
*attr=FileAttr(de.name,*attr);
}
UnlockPartition(p);
} catch
UnlockPartition(p);
}
return buf;
}
BoolU8 CdLT(I1 *name,U8 cur_dir_cluster)
{
LTDirEntry de;
if (Fs->cur_partition->type!=PT_LT)
PutSysTextErr("ST_NOT_LT");
else {
if (FindLTFile(Fs->cur_partition,cur_dir_cluster,
name,&de,TRUE,FALSE,TRUE)) {
return TRUE;
} else {
cout name," ";
PutSysTextErr("ST_FILE_NOT_FOUND");
}
}
return FALSE;
}
void FreeLTClusters(LTPartition *p,U8 c,U8 cnt,BoolU4 unlock)
{
LTFreeList *tempf;
BoolU4 found=FALSE;
CheckLTPartition(p);
if (!c) return;
if (p->type!=PT_LT)
PutSysTextErr("ST_NOT_LT");
else {
try {
LockPartition(p);
if (!p->next_free)
BuildLTFreeList(p,FALSE);
tempf=p->next_free;
while (!found && tempf!=&p->next_free) {
if (tempf->start+tempf->size==c) {
tempf->size+=cnt;
found=TRUE;
} else if (c+cnt==tempf->start) {
tempf->size+=cnt;
tempf->start=c;
found=TRUE;
}
tempf=tempf->next;
}
if (!found) {
tempf=AMAlloc(sizeof(LTFreeList));
tempf->size=cnt;
tempf->start=c;
InsQue(tempf,p->last_free);
}
while (cnt--) {
SetLTBuf(p,c);
Btr(p->cur_MAP_blk,c&(BLK_SIZE<<3-1));
Bts(p->buffered_MAP_dirty_bits,0);
c++;
}
CleanMAPBuf(p);
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
}
}
U8 AllocLTClusters(LTPartition *p,U8 cnt, BoolU4 unlock)
{
LTFreeList *tempf,*best_free=NULL;
U8 i,first,best_size=MAX_U8;
if (!cnt)
Debugger;
try {
LockPartition(p);
if (!p->next_free)
BuildLTFreeList(p,FALSE);
tempf=p->next_free;
while (tempf!=&p->next_free) {
if (tempf->size>=cnt && tempf->size<best_size) {
best_free=tempf;
best_size=tempf->size;
if (tempf->size==cnt)
break;
}
tempf=tempf->next;
}
if (!best_free)
Debugger;
first=best_free->start;
for (i=0;i<cnt;i++) {
SetLTBuf(p,first+i);
Bts(p->cur_MAP_blk,(first+i)&(BLK_SIZE<<3-1));
Bts(p->buffered_MAP_dirty_bits,0);
}
CleanMAPBuf(p);
if (best_free->size-=cnt)
best_free->start+=cnt;
else {
RemQue(best_free);
AFree(best_free);
}
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
return first;
}
BoolU8 NewLTDirEntry2(LTPartition *p,I1 *cur_dir,LTDirEntry *de,BoolU4 free_old_chain,BoolU4 unlock)
{
LTDirEntry *buf,*buf2,*ptr,de2;
LTBootStruct *br;
U8 c,i=1,j=0,n=BLK_SIZE/LT_DIR_ENTRY_SIZE,dir_size;
BoolU4 written=FALSE;
U1 ch;
U8 cur_dir_cluster=NameToDirCluster(p,cur_dir,unlock);
I1 *temp,*parent_dir;
try {
de->attr|=LT_ATTR_CONTIGUOUS;
LockPartition(p);
buf2=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(p,buf2,cur_dir_cluster,1,FALSE);
ptr=buf2-offset(LTDirEntry.start);
buf=MAlloc(ptr->size);
RClusters(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS/p->spc,FALSE);
dir_size=ptr->size;
ptr=buf-offset(LTDirEntry.start)+LT_DIR_ENTRY_SIZE;
Free(buf2);
while (TRUE) {
ch=ptr->name[0];
if (!ch) {
if (!written)
MemCpy(&ptr->start,&de->start,LT_DIR_ENTRY_SIZE);
if ((i+1)*LT_DIR_ENTRY_SIZE+j<<BLK_SIZE_BITS<dir_size)
WBlks(p,buf+j<<BLK_SIZE_BITS,
p->data+cur_dir_cluster*p->spc+j,1,FALSE);
else {
buf2=MAllocZ(dir_size+p->spc<<BLK_SIZE_BITS);
MemCpy(buf2,buf,dir_size);
FreeLTClusters(p,cur_dir_cluster,
dir_size/(p->spc<<BLK_SIZE_BITS),FALSE);
dir_size+=p->spc<<BLK_SIZE_BITS;
c=AllocClusters(p,0,dir_size/(p->spc<<BLK_SIZE_BITS),TRUE,FALSE);
Free(buf);
buf=buf2;
ptr=buf-offset(LTDirEntry.start);
ptr->size=dir_size;
ptr->expanded_size=dir_size;
ptr->cluster=c;
WClusters(p,buf,c,dir_size/(p->spc<<BLK_SIZE_BITS),FALSE);
if (cur_dir_cluster==p->root_cluster) {
br=MAllocZ(BLK_SIZE);
RBlks(p,br,p->offset,1,FALSE);
br->root_cluster=c;
WBlks(p,br,p->offset,1,FALSE);
Free(br);
p->root_cluster=c;
} else {
temp=NewStr(cur_dir);
parent_dir=NewStr(cur_dir);
RemoveLastSeg(parent_dir,"/",temp);
if (!*parent_dir) {
Free(parent_dir);
parent_dir=NewStr("/");
}
if (FindLTFile(p,NameToDirCluster(p,parent_dir,FALSE),
temp,&de2,TRUE,FALSE,FALSE)) {
de2.cluster=c;
de2.size=dir_size;
de2.expanded_size=dir_size;
//TODO: is this supposed to free old chain?
NewLTDirEntry2(p,parent_dir,&de2,FALSE,FALSE);
} else
Debugger;
Free(temp);
Free(parent_dir);
}
}
break;
} else if (ptr->attr & LT_ATTR_DELETED) {
if (!written) {
MemCpy(&ptr->start,&de->start,LT_DIR_ENTRY_SIZE);
WBlks(p,buf+j<<BLK_SIZE_BITS,
p->data+cur_dir_cluster*p->spc+j,1,FALSE);
written=TRUE;
}
} else {
if (!StrCmp(de->name,ptr->name)) {
if (free_old_chain)
FreeLTClusters(p,ptr->cluster,
(ptr->size+p->spc<<BLK_SIZE_BITS-1)/(p->spc<<BLK_SIZE_BITS),FALSE);
if (!written)
MemCpy(&ptr->start,&de->start,LT_DIR_ENTRY_SIZE);
else
ptr->attr|=LT_ATTR_DELETED;
WBlks(p,buf+j<<BLK_SIZE_BITS,
p->data+cur_dir_cluster*p->spc+j,1,FALSE);
break;
}
}
ptr+=LT_DIR_ENTRY_SIZE;
if (++i>=n) {
j++;
i=0;
}
}
Free(buf);
if (unlock)
UnlockPartition(p);
} catch
if (unlock)
UnlockPartition(p);
return FALSE;
}
BoolU8 DelLTFiles(LTPartition *p,I1 *cur_dir,I1 *wild,
BoolU4 del_dir=FALSE,BoolU4 print_msg=TRUE)
{
LTDirEntry *buf,*buf2,*ptr;
U8 i=0,j=0,n=BLK_SIZE/LT_DIR_ENTRY_SIZE;
U1 ch;
U8 cur_dir_cluster=NameToDirCluster(p,cur_dir,TRUE);
try {
LockPartition(p);
buf2=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(p,buf2,cur_dir_cluster,1,FALSE);
ptr=buf2-offset(LTDirEntry.start);
buf=MAlloc(ptr->size);
RClusters(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS/p->spc,FALSE);
Free(buf2);
ptr=buf-offset(LTDirEntry.start);
ptr->name[0]='.';
ptr->name[1]=0;
while (TRUE) {
ch=ptr->name[0];
if (!ch)
break;
else if (!(ptr->attr & LT_ATTR_DELETED) && ch!='.' && (del_dir ||
!(ptr->attr & LT_ATTR_DIR))) {
if (WildFileNameList(wild,ptr->name)) {
if (print_msg)
coutln SysText("ST_DELETE"),ptr->name;
ptr->attr|=LT_ATTR_DELETED;
WBlks(p,buf+j<<BLK_SIZE_BITS,
p->data+cur_dir_cluster*p->spc+j,1,FALSE);
FreeLTClusters(p,ptr->cluster,
(ptr->size+p->spc<<BLK_SIZE_BITS-1)/(p->spc<<BLK_SIZE_BITS),FALSE);
}
}
ptr+=LT_DIR_ENTRY_SIZE;
if (++i>=n) {
j++;
i=0;
}
}
Free(buf);
UnlockPartition(p);
} catch
UnlockPartition(p);
return FALSE;
}
U8 WriteLTFile(LTPartition *p,I1 *cur_dir,I1 *name,U1 *buf,U8 size,
LTDate LTdatetime,U8 attr,BoolU4 raw,
ArcCompressStruct **ac2)
{
LTDirEntry de;
U8 c=0;
U8 flags=0,cluster_cnt,
cluster_size=p->spc<<BLK_SIZE_BITS;
ArcCompressStruct *ac=NULL;
BoolU4 contiguous;
U8 cur_dir_cluster=NameToDirCluster(p,cur_dir,TRUE);
MemSet(&de,0,sizeof(LTDirEntry));
if (ac2) *ac2=NULL;
if (!LTdatetime)
LTdatetime=GetCurTimeLTDate;
if (p->type!=PT_LT)
PutSysTextErr("ST_NOT_LT");
else if (!ToLTFilename(de.name,name))
PutSysTextErr("ST_INVALID_FILENAME");
else {
DelLTFiles(p,cur_dir,de.name,FALSE,FALSE);
attr=FileAttr(name,attr);
attr|=LT_ATTR_CONTIGUOUS;
contiguous=TRUE;
de.expanded_size=size;
if ((attr & LT_ATTR_COMPRESSED) && !raw) {
ac=CompressBuf(buf,size,flags);
size=ac->compressed_size;
buf=ac;
}
de.size=size;
de.xsum=ArcCheckSum(buf,size)^LT_XSUM;
cluster_cnt=(size+cluster_size-1)/cluster_size;
if (cluster_cnt)
c=AllocClusters(p,0,cluster_cnt,contiguous,TRUE);
else
c=INVALID_CLUSTER;
de.cluster=c;
de.attr=attr;
de.datetime=LTdatetime;
if (cluster_cnt)
WClusters(p,buf,c,cluster_cnt,TRUE,TRUE);
NewLTDirEntry2(p,cur_dir,&de,TRUE,TRUE);
if (ac2)
*ac2=ac;
else
Free(ac);
}
return c;
}
LTDirEntry *FindLTFiles(I1 *wild,U8 fuf_flags,LTDirEntry *parent=NULL)
{
LTPartition *p=Fs->cur_partition;
LTDirEntry *buf,*buf2,*ptr;
U8 cur_dir_cluster=NameToDirCluster(p,Fs->cur_dir,FALSE);
U1 ch;
LTDirEntry *result=NULL,*tempm;
LockPartition(p);
buf2=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(p,buf2,cur_dir_cluster,1,FALSE);
ptr=buf2-offset(LTDirEntry.start);
buf=MAlloc(ptr->size);
RClusters(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS/p->spc,FALSE);
Free(buf2);
ptr=buf-offset(LTDirEntry.start);
ptr->name[0]='.';
ptr->name[1]=0;
ptr+=LT_DIR_ENTRY_SIZE;
ptr->cluster=NameToParentDirCluster(p,Fs->cur_dir,FALSE);
ptr-=LT_DIR_ENTRY_SIZE;
while (TRUE) {
ch=ptr->name[0];
if (!ch)
break;
else if (!(ptr->attr & LT_ATTR_DELETED)) {
tempm=MAllocZ(sizeof(LTDirEntry));
MemCpy(&tempm->start,&ptr->start,LT_DIR_ENTRY_SIZE);
tempm->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && tempm->attr & LT_ATTR_DIR && tempm->name[0]!='.') {
tempm->next=result;
result=tempm;
tempm->full_name=AbsoluteDirName(tempm->name);
UnlockPartition(p);
Cd(tempm->name);
tempm->sub=FindLTFiles(wild,fuf_flags,tempm);
Cd("..");
LockPartition(p);
} else if ((!(tempm->attr & LT_ATTR_DIR) && !Bt(&fuf_flags,FUf_JUST_DIRS)
|| !Bt(&fuf_flags,FUf_RECURSE)) &&
!(Bt(&fuf_flags,FUf_RECURSE) && tempm->name[0]=='.') &&
WildFileNameList(wild,tempm->name)) {
tempm->next=result;
result=tempm;
tempm->full_name=AbsoluteFileName(tempm->name);
} else
DelLTDirEntry(tempm);
}
ptr+=LT_DIR_ENTRY_SIZE;
}
Free(buf);
UnlockPartition(p);
return result;
}