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)<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;iowning_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 (++ifile_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_NULLtypebd,except); else return NULL; }