using System; using System.Linq; using Spd; using Spd.Interop; using SvdCli.Storage; namespace SvdCli.DriverAdapt { public class VirtualDrive { private readonly ISvdStorage _storage; private readonly SpdImplement _spdImplement; private readonly StorageUnitHost _host; public long Size { get; } public VirtualDrive(ISvdStorage storage) { _storage = storage; _spdImplement = new SpdImplement(_storage); _host = new StorageUnitHost(_spdImplement) { ProductId = storage.ProductId, ProductRevisionLevel = storage.ProductVersion, WriteProtected = storage.WriteProtect, UnmapSupported = storage.SupportTrim, BlockCount = storage.BlockCount, BlockLength = storage.BlockSize, MaxTransferLength = storage.MaxTransferLength, CacheSupported = true, EjectDisabled = false, Guid = Guid.NewGuid(), }; Size = storage.BlockSize * storage.BlockSize; } public void Attach() { _storage.Init(); _host.Start(); } public void Detach() { _host.Shutdown(); _storage.Exit(); } private class SpdImplement : StorageUnitBase { private readonly ISvdStorage _storage; public SpdImplement(ISvdStorage storage) => _storage = storage; public override void Read(byte[] buffer, ulong blockAddress, uint blockCount, bool flush, ref StorageUnitStatus status) { if (flush) _storage.Flush(); _storage.ReadBlocks(buffer, blockAddress, blockCount); } public override void Write(byte[] buffer, ulong blockAddress, uint blockCount, bool flush, ref StorageUnitStatus status) { _storage.WriteBlocks(buffer, blockAddress, blockCount); if (flush) _storage.Flush(); } public override void Flush(ulong blockAddress, uint blockCount, ref StorageUnitStatus status) { _storage.Flush(); } public override void Unmap(UnmapDescriptor[] descriptors, ref StorageUnitStatus status) { var trimDescriptors = descriptors.Select(p => new TrimDescriptor((long)p.BlockAddress * _storage.BlockSize, p.BlockCount * _storage.BlockSize)).ToArray(); _storage.Trim(trimDescriptors); } } } }