SCSICommandDescriptorBlock.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* Copyright (C) 2012-2016 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text;
  10. using Utilities;
  11. namespace SCSI
  12. {
  13. public abstract class SCSICommandDescriptorBlock
  14. {
  15. public SCSIOpCodeName OpCode;
  16. public byte MiscellaneousCDBInformationHeader;
  17. public ServiceAction ServiceAction;
  18. public uint AdditionalCDBdata;
  19. public uint LogicalBlockAddress;
  20. public uint TransferLength; // number of blocks, also doubles as Parameter list length / Allocation length
  21. public byte MiscellaneousCDBinformation;
  22. public byte Control;
  23. protected SCSICommandDescriptorBlock()
  24. {
  25. }
  26. public abstract byte[] GetBytes();
  27. public static SCSICommandDescriptorBlock FromBytes(byte[] buffer, int offset)
  28. {
  29. byte opCode = buffer[offset + 0];
  30. switch ((SCSIOpCodeName)opCode)
  31. {
  32. case SCSIOpCodeName.TestUnitReady:
  33. return new SCSICommandDescriptorBlock6(buffer, offset);
  34. case SCSIOpCodeName.RequestSense:
  35. return new SCSICommandDescriptorBlock6(buffer, offset);
  36. case SCSIOpCodeName.Read6:
  37. return new SCSICommandDescriptorBlock6(buffer, offset);
  38. case SCSIOpCodeName.Write6:
  39. return new SCSICommandDescriptorBlock6(buffer, offset);
  40. case SCSIOpCodeName.Inquiry:
  41. return new InquiryCommand(buffer, offset);
  42. case SCSIOpCodeName.Reserve6:
  43. return new SCSICommandDescriptorBlock6(buffer, offset);
  44. case SCSIOpCodeName.Release6:
  45. return new SCSICommandDescriptorBlock6(buffer, offset);
  46. case SCSIOpCodeName.ModeSense6:
  47. return new ModeSense6CommandDescriptorBlock(buffer, offset);
  48. case SCSIOpCodeName.ReadCapacity10:
  49. return new SCSICommandDescriptorBlock10(buffer, offset);
  50. case SCSIOpCodeName.Read10:
  51. return new SCSICommandDescriptorBlock10(buffer, offset);
  52. case SCSIOpCodeName.Write10:
  53. return new SCSICommandDescriptorBlock10(buffer, offset);
  54. case SCSIOpCodeName.Verify10:
  55. return new SCSICommandDescriptorBlock10(buffer, offset);
  56. case SCSIOpCodeName.SynchronizeCache10:
  57. return new SCSICommandDescriptorBlock10(buffer, offset);
  58. case SCSIOpCodeName.WriteSame10:
  59. return new SCSICommandDescriptorBlock10(buffer, offset);
  60. case SCSIOpCodeName.Read16:
  61. return new SCSICommandDescriptorBlock16(buffer, offset);
  62. case SCSIOpCodeName.Write16:
  63. return new SCSICommandDescriptorBlock16(buffer, offset);
  64. case SCSIOpCodeName.Verify16:
  65. return new SCSICommandDescriptorBlock16(buffer, offset);
  66. case SCSIOpCodeName.WriteSame16:
  67. return new SCSICommandDescriptorBlock16(buffer, offset);
  68. case SCSIOpCodeName.ServiceActionIn16:
  69. return new SCSICommandDescriptorBlock16(buffer, offset);
  70. case SCSIOpCodeName.ReportLUNs:
  71. return new SCSICommandDescriptorBlock12(buffer, offset);
  72. default:
  73. throw new UnsupportedSCSICommandException(String.Format("Unknown SCSI command: 0x{0}", opCode.ToString("x")));
  74. }
  75. }
  76. public static SCSICommandDescriptorBlock Create(SCSIOpCodeName opCode)
  77. {
  78. switch (opCode)
  79. {
  80. case SCSIOpCodeName.TestUnitReady:
  81. return new SCSICommandDescriptorBlock6(opCode);
  82. case SCSIOpCodeName.RequestSense:
  83. return new SCSICommandDescriptorBlock6(opCode);
  84. case SCSIOpCodeName.Read6:
  85. return new SCSICommandDescriptorBlock6(opCode);
  86. case SCSIOpCodeName.Write6:
  87. return new SCSICommandDescriptorBlock6(opCode);
  88. case SCSIOpCodeName.Inquiry:
  89. return new InquiryCommand();
  90. case SCSIOpCodeName.Reserve6:
  91. return new SCSICommandDescriptorBlock6(opCode);
  92. case SCSIOpCodeName.Release6:
  93. return new SCSICommandDescriptorBlock6(opCode);
  94. case SCSIOpCodeName.ModeSense6:
  95. return new ModeSense6CommandDescriptorBlock();
  96. case SCSIOpCodeName.ReadCapacity10:
  97. return new SCSICommandDescriptorBlock10(opCode);
  98. case SCSIOpCodeName.Read10:
  99. return new SCSICommandDescriptorBlock10(opCode);
  100. case SCSIOpCodeName.Write10:
  101. return new SCSICommandDescriptorBlock10(opCode);
  102. case SCSIOpCodeName.Verify10:
  103. return new SCSICommandDescriptorBlock10(opCode);
  104. case SCSIOpCodeName.SynchronizeCache10:
  105. return new SCSICommandDescriptorBlock10(opCode);
  106. case SCSIOpCodeName.WriteSame10:
  107. return new SCSICommandDescriptorBlock10(opCode);
  108. case SCSIOpCodeName.Read16:
  109. return new SCSICommandDescriptorBlock16(opCode);
  110. case SCSIOpCodeName.Write16:
  111. return new SCSICommandDescriptorBlock16(opCode);
  112. case SCSIOpCodeName.Verify16:
  113. return new SCSICommandDescriptorBlock16(opCode);
  114. case SCSIOpCodeName.WriteSame16:
  115. return new SCSICommandDescriptorBlock16(opCode);
  116. case SCSIOpCodeName.ServiceActionIn16:
  117. return new SCSICommandDescriptorBlock16(opCode);
  118. case SCSIOpCodeName.ReportLUNs:
  119. return new SCSICommandDescriptorBlock12(opCode);
  120. default:
  121. throw new NotImplementedException("SCSI opcode not implemented");
  122. }
  123. }
  124. public ulong LogicalBlockAddress64
  125. {
  126. get
  127. {
  128. if (this is SCSICommandDescriptorBlock16)
  129. {
  130. ulong result = (ulong)this.LogicalBlockAddress << 32;
  131. result += this.AdditionalCDBdata;
  132. return result;
  133. }
  134. else
  135. {
  136. return this.LogicalBlockAddress;
  137. }
  138. }
  139. set
  140. {
  141. if (this is SCSICommandDescriptorBlock16)
  142. {
  143. this.LogicalBlockAddress = (uint)(value >> 32);
  144. this.AdditionalCDBdata = (uint)(value & 0xFFFFFFFF);
  145. }
  146. else
  147. {
  148. this.LogicalBlockAddress = (uint)value;
  149. }
  150. }
  151. }
  152. }
  153. }