templeos-info/public/Wb/Kernel/BlkDev/DskBlkDev.HC

188 lines
4.7 KiB
HolyC
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Bool BlkDevLock(CBlkDev *bd)
{//Make this task have exclusive access to BlkDev.
BlkDevChk(bd);
while (bd->lock_fwding)
bd=bd->lock_fwding; //If two blkdevs on same controller, use just one lock
if (!Bt(&bd->locked_flags,BDlf_LOCKED) || bd->owning_task!=Fs) {
while (LBts(&bd->locked_flags,BDlf_LOCKED))
Yield;
bd->owning_task=Fs;
return TRUE;
} else
return FALSE;
}
Bool BlkDevUnlock(CBlkDev *bd,Bool rst=FALSE)
{//Release exclusive lock on access to BlkDev.
BlkDevChk(bd);
while (bd->lock_fwding)
bd=bd->lock_fwding; //If two blkdevs on same controller, use just one lock
if (Bt(&bd->locked_flags,BDlf_LOCKED) && bd->owning_task==Fs) {
if (rst)
bd->flags&=~(BDF_INITIALIZED|BDF_INIT_IN_PROGRESS);
bd->owning_task=NULL;
LBtr(&bd->locked_flags,BDlf_LOCKED);
Yield; //Prevent deadlock
return TRUE;
} else
return FALSE;
}
Bool BlkDevInit(CBlkDev *bd)
{
CDirEntry de;
U8 buf[STR_LEN];
CDrv *dv=Let2Drv(bd->first_drv_let);
Bool res=FALSE;
if (!LBts(&bd->flags,BDf_INITIALIZED)) {
bd->flags|=BDF_INIT_IN_PROGRESS;
switch (bd->type) {
case BDT_RAM:
if (!bd->RAM_dsk) {
bd->RAM_dsk=AMAlloc((bd->max_blk+1)<<BLK_SIZE_BITS);
bd->max_blk=MSize(bd->RAM_dsk)>>BLK_SIZE_BITS-1;
}
dv->fs_type=FSt_REDSEA;
dv->size=bd->max_blk+1-bd->drv_offset;
if (RedSeaValidate(bd->first_drv_let))
RedSeaInit(dv);
else
RedSeaFmt(bd->first_drv_let);
res=TRUE;
break;
case BDT_ISO_FILE_READ:
if (FileFind(bd->file_dsk_name,&de,FUF_JUST_FILES)) {
bd->max_blk=de.size>>BLK_SIZE_BITS-1;
try bd->file_dsk=FOpen(bd->file_dsk_name,"rc",bd->max_blk+1);
catch {
if (Fs->except_ch=='File')
PrintErr("Not Contiguous.Move file to filename.ISO.C.\n");
Fs->catch_except=TRUE;
}
if (bd->file_dsk) {
dv->fs_type=FSt_REDSEA;
dv->size=bd->max_blk+1-bd->drv_offset;
if (RedSeaValidate(bd->first_drv_let)) {
RedSeaInit(dv);
res=TRUE;
} else
PrintErr("Not RedSea\n");
}
}
break;
case BDT_ISO_FILE_WRITE:
if (!bd->file_dsk_name) {
StrPrint(buf,"%C:/Drv%C.ISO.C",
blkdev.boot_drv_let,bd->first_drv_let);
bd->file_dsk_name=AStrNew(buf);
}
if (bd->max_blk<7)
bd->max_blk=7;
bd->file_dsk=FOpen(bd->file_dsk_name,"wc",bd->max_blk+1);
dv->fs_type=FSt_REDSEA;
dv->size=bd->max_blk+1-bd->drv_offset;
RedSeaFmt(bd->first_drv_let);
CallExtStr("RedSeaISO9660",bd->file_dsk_name,bd->first_drv_let);
res=TRUE;
break;
case BDT_ATA:
bd->max_reads=128;
bd->max_writes=1;
res=ATAInit(bd);
break;
case BDT_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>blkdev.cache_size/BLK_SIZE/4)
bd->max_reads=blkdev.cache_size/BLK_SIZE/4 & ~3;
if (bd->max_reads<128)
bd->max_reads=128;
bd->max_writes=0xFFFF*4;
if (res=ATAInit(bd))
dv->size=bd->max_blk+1;
break;
}
if (res && bd->flags & BDF_READ_CACHE)
DskCacheInvalidate(dv);
bd->flags&=~BDF_INIT_IN_PROGRESS;
} else
res=TRUE;
return res;
}
U0 BlkDevsRelease()
{//When task dies, release all owned BlkDevs.
I64 i;
CBlkDev *bd;
for (i=0;i<BLKDEVS_NUM;i++) {
bd=&blkdev.blkdevs[i];
if (bd->owning_task==Fs && bd->bd_signature==BD_SIGNATURE_VAL)
BlkDevUnlock(bd,TRUE);
}
}
CBlkDev *BlkDevNextFreeSlot(U8 first_drv_let,I64 type)
{//Locate free slot for new BlkDev, like during $LK,"Mount",A="MN:Mount"$().
I64 i=0;
CBlkDev *res;
if (Let2BlkDevType(first_drv_let)!=type)
throw('BlkDev');
do {
res=&blkdev.blkdevs[i];
if (res->bd_signature!=BD_SIGNATURE_VAL) {
MemSet(res,0,sizeof(CBlkDev));
res->first_drv_let=first_drv_let;
res->type=type;
res->flags=BDF_READ_CACHE;
res->blk_size=BLK_SIZE;
res->max_blk=0xEFFFFFFF;
switch (type) {
case BDT_RAM:
res->flags&=~BDF_READ_CACHE;
break;
case BDT_ISO_FILE_READ:
res->flags|=BDF_READ_ONLY;
break;
case BDT_ATAPI:
res->flags|=BDF_REMOVABLE|BDF_READ_ONLY;
res->blk_size=DVD_BLK_SIZE;
break;
}
return res;
}
} while (++i<BLKDEVS_NUM);
throw('BlkDev');
return NULL; //never gets here
}
U0 BlkDevDel(CBlkDev *bd)
{//Delete BlkDev
DrvBlkDevDel(bd);
FClose(bd->file_dsk);
Free(bd->file_dsk_name);
Free(bd->dev_id_record);
MemSet(bd,0,sizeof(CBlkDev));
}
CBlkDev *BlkDevChk(CBlkDev *bd,Bool except=TRUE)
{//Check for valid BlkDev. Throw exception.
if (!bd || bd->bd_signature!=BD_SIGNATURE_VAL ||
!(BDT_NULL<bd->type<BDT_TYPES_NUM)) {
if (except)
throw('BlkDev');
else
return NULL;
} else
return bd;
}
CBlkDev *Let2BlkDev(U8 drv_let=0,Bool except=TRUE)
{//Drv letter to BlkDev ptr.
CDrv *dv;
if (dv=Let2Drv(drv_let,except))
return BlkDevChk(dv->bd,except);
else
return NULL;
}