VirtualDrive.cs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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 = Guid.NewGuid(),
  30. };
  31. Size = storage.BlockSize * storage.BlockSize;
  32. }
  33. public void Attach()
  34. {
  35. _storage.Init();
  36. _host.Start();
  37. }
  38. public void Detach()
  39. {
  40. _host.Shutdown();
  41. _storage.Exit();
  42. }
  43. private class SpdImplement : StorageUnitBase
  44. {
  45. private readonly ISvdStorage _storage;
  46. public SpdImplement(ISvdStorage storage) => _storage = storage;
  47. public override void Read(byte[] buffer, ulong blockAddress, uint blockCount, bool flush, ref StorageUnitStatus status)
  48. {
  49. if (flush) _storage.Flush();
  50. _storage.ReadBlocks(buffer, blockAddress, blockCount);
  51. }
  52. public override void Write(byte[] buffer, ulong blockAddress, uint blockCount, bool flush, ref StorageUnitStatus status)
  53. {
  54. _storage.WriteBlocks(buffer, blockAddress, blockCount);
  55. if (flush) _storage.Flush();
  56. }
  57. public override void Flush(ulong blockAddress, uint blockCount, ref StorageUnitStatus status)
  58. {
  59. _storage.Flush();
  60. }
  61. public override void Unmap(UnmapDescriptor[] descriptors, ref StorageUnitStatus status)
  62. {
  63. var trimDescriptors = descriptors.Select(p => new TrimDescriptor((long)p.BlockAddress * _storage.BlockSize, p.BlockCount * _storage.BlockSize)).ToArray();
  64. _storage.Trim(trimDescriptors);
  65. }
  66. }
  67. }
  68. }