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 result=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->type=DVT_REDSEA; dv->size=bd->max_blk+1; if (RedSeaDrvValidate(bd->first_drv_let)) RedSeaDrvInit(dv); else RedSeaFmt(bd->first_drv_let); result=TRUE; break; case BDT_ATA: bd->max_reads=128; bd->max_writes=1; result=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 (result=ATAInit(bd)) dv->size=bd->max_blk+1; break; } if (result && bd->flags & BDF_READ_CACHE) DskCacheInvalidate(dv); bd->flags&=~BDF_INIT_IN_PROGRESS; } else result=TRUE; return result; } 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 *result; do { result=&blkdev.blkdevs[i]; if (result->bd_signature!=BD_SIGNATURE_VAL) { MemSet(result,0,sizeof(CBlkDev)); result->first_drv_let=first_drv_let; result->type=type; if (type==BDT_ATAPI) result->flags=BDF_REMOVABLE; else result->flags=0; if (type!=BDT_RAM) result->flags|=BDF_READ_CACHE; if (type==BDT_ATAPI) { result->blk_size=DVD_BLK_SIZE; result->flags|=BDF_READ_ONLY; } else result->blk_size=BLK_SIZE; result->max_blk=0xEFFFFFFF; return result; } } while (++ibd_signature!=BD_SIGNATURE_VAL || !(BDT_NULLtypebd; BlkDevChk(bd); return bd; }