#define ZERO_BUF_SIZE 	2048
U0 BlkWriteZero(CDrive *drive, I64 blk, I64 count)
{//Fill blk count with zeros in Drive.
	I64  n;
	U8	*z = CAlloc(ZERO_BUF_SIZE << BLK_SIZE_BITS);
	Bool show_progress;

	if (count > ZERO_BUF_SIZE && drive->bd->type != BDT_RAM)
	{
		progress1 = 0;
		progress1_max = count;
		StrCopy(progress1_desc, "Zeroing");
		show_progress = TRUE;
	}
	else
		show_progress = FALSE;
	while (count > 0)
	{
		n = count;
		if (n > ZERO_BUF_SIZE)
			n = ZERO_BUF_SIZE;
		BlkWrite(drive, z, blk, n);
		blk += n;
		count -= n;
		if (show_progress)
			progress1 += n;
		Yield;	//Prevent locking
	}
	Free(z);
	if (show_progress)
	{
		*progress1_desc = 0;
		progress1 = progress1_max = 0;
	}
}

Bool BlkRead(CDrive *drive, U8 *buf, I64 blk, I64 count)
{//Read blk count from Drive to buf.
	Bool	 res = TRUE, unlock;
	CBlkDev	*bd  = drive->bd;

	if (count <= 0)
		return TRUE;
	DriveCheck(drive);
	try
	{
		unlock = DriveLock(drive);
		BlkDevInit(bd);
		if (drive->drv_offset && blk<drive->drv_offset || blk + count>drive->drv_offset + drive->size)
			throw('Drive');
		if (bd->flags & BDF_READ_CACHE)
			RCache(drive, &buf, &blk, &count);
		if (count > 0)
		{
			switch (bd->type)
			{
				case BDT_RAM:
					MemCopy(buf, bd->RAM_disk + blk << BLK_SIZE_BITS, count << BLK_SIZE_BITS);
					break;

				case BDT_ISO_FILE_READ:
				case BDT_ISO_FILE_WRITE:
					FBlkRead(bd->file_disk, buf, blk, count);
					break;

				case BDT_ATA:
				case BDT_ATAPI:
					res = ATARBlks(drive, buf, blk, count);
					break;
			}
			bd->last_time = tS;
			if (bd->flags & BDF_READ_CACHE)
				DiskCacheAdd(drive, buf, blk, count);
		}
		if (unlock)
			DriveUnlock(drive);
	}
	catch
		if (unlock)
			DriveUnlock(drive);

	return res;
}

Bool BlkWrite(CDrive *drive, U8 *buf, I64 blk, I64 count)
{//Write blk count from buf to Drive.
	Bool	 res = TRUE, unlock;
	CBlkDev	*bd  = drive->bd;

	if (count <= 0)
		return TRUE;
	DriveCheck(drive);
	try
	{
		unlock = DriveLock(drive);
		BlkDevInit(bd);
		if (bd->flags & BDF_READ_ONLY && !(bd->flags & BDF_READ_ONLY_OVERRIDE))
			throw('BlkDev');
		if (drive->drv_offset && blk<drive->drv_offset || blk + count>drive->drv_offset + drive->size)
			throw('Drive');
		if (count > 0)
		{
			switch (bd->type)
			{
				case BDT_RAM:
					MemCopy(bd->RAM_disk + blk << BLK_SIZE_BITS, buf, count << BLK_SIZE_BITS);
					break;

				case BDT_ISO_FILE_READ:
				case BDT_ISO_FILE_WRITE:
					FBlkWrite(bd->file_disk, buf, blk, count);
					break;

				case BDT_ATA:
				case BDT_ATAPI:
					res = ATAWBlks(drive, buf, blk, count);
					break;
			}
			bd->last_time = tS;
			if (bd->flags & BDF_READ_CACHE)
				DiskCacheAdd(drive, buf, blk, count);
		}
		if (unlock)
			DriveUnlock(drive);
	}
	catch
		if (unlock)
			DriveUnlock(drive);

	return res;
}
