VirtualDrive.cs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. using System;
  2. using System.Linq;
  3. using Spd;
  4. using Spd.Interop;
  5. using SvdCli.Storage;
  6. namespace SvdCli.DriverAdapt
  7. {
  8. public class VirtualDrive
  9. {
  10. private readonly ISvdStorage _storage;
  11. private readonly SpdImplement _spdImplement;
  12. private readonly StorageUnitHost _host;
  13. public long Size { get; }
  14. public VirtualDrive(ISvdStorage storage)
  15. {
  16. _storage = storage;
  17. _spdImplement = new SpdImplement(_storage);
  18. _host = new StorageUnitHost(_spdImplement)
  19. {
  20. ProductId = storage.ProductId,
  21. ProductRevisionLevel = storage.ProductVersion,
  22. WriteProtected = storage.WriteProtect,
  23. UnmapSupported = storage.SupportTrim,
  24. BlockCount = storage.BlockCount,
  25. BlockLength = storage.BlockSize,
  26. MaxTransferLength = storage.MaxTransferLength,
  27. CacheSupported = true,
  28. EjectDisabled = false,
  29. Guid = storage.Guid,
  30. };
  31. Size = storage.BlockSize * storage.BlockSize;
  32. }
  33. public void Attach()
  34. {
  35. _storage.Init();
  36. _host.Start();
  37. _storage.FireMountedEvent();
  38. }
  39. public void Detach()
  40. {
  41. _host.Shutdown();
  42. _storage.Exit();
  43. }
  44. private class SpdImplement : StorageUnitBase
  45. {
  46. private readonly ISvdStorage _storage;
  47. public SpdImplement(ISvdStorage storage) => _storage = storage;
  48. public override void Read(byte[] buffer, ulong blockAddress, uint blockCount, bool flush, ref StorageUnitStatus status)
  49. {
  50. if (flush) _storage.Flush();
  51. _storage.ReadBlocks(buffer, blockAddress, blockCount);
  52. }
  53. public override void Write(byte[] buffer, ulong blockAddress, uint blockCount, bool flush, ref StorageUnitStatus status)
  54. {
  55. _storage.WriteBlocks(buffer, blockAddress, blockCount);
  56. if (flush) _storage.Flush();
  57. }
  58. public override void Flush(ulong blockAddress, uint blockCount, ref StorageUnitStatus status)
  59. {
  60. _storage.Flush();
  61. }
  62. public override void Unmap(UnmapDescriptor[] descriptors, ref StorageUnitStatus status)
  63. {
  64. var trimDescriptors = descriptors.Select(p => new TrimDescriptor((long)p.BlockAddress * _storage.BlockSize, p.BlockCount * _storage.BlockSize)).ToArray();
  65. _storage.Trim(trimDescriptors);
  66. }
  67. }
  68. }
  69. }