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) { 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; if (RedSeaDrvValidate(bd->first_drv_let)) RedSeaDrvInit(dv); else RedSeaFmt(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 *BlkDevNextFree(U8 first_drv_let,I64 type) {//Locate free slot for new BlkDev, like during $LK,"Mount",A="MN:Mount"$(). I64 i=0; CBlkDev *res; 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; if (type==BDT_ATAPI) res->flags=BDF_REMOVABLE; else res->flags=0; if (type!=BDT_RAM) res->flags|=BDF_READ_CACHE; if (type==BDT_ATAPI) { res->blk_size=DVD_BLK_SIZE; res->flags|=BDF_READ_ONLY; } else res->blk_size=BLK_SIZE; res->max_blk=0xEFFFFFFF; return res; } } while (++ibd_signature!=BD_SIGNATURE_VAL || !(BDT_NULLtypebd,except); else return NULL; }