SCSIDataInPDU.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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 SCSI;
  11. using Utilities;
  12. namespace ISCSI
  13. {
  14. // Data-In = Data sent to the initiator (READ operations)
  15. public class SCSIDataInPDU : ISCSIPDU
  16. {
  17. public bool Acknowledge;
  18. public bool ResidualOverflow;
  19. public bool ResidualUnderflow;
  20. public bool StatusPresent; // indicate that the Command Status field contains status
  21. public SCSIStatusCodeName Status;
  22. public LUNStructure LUN;
  23. public uint TargetTransferTag;
  24. public uint StatSN;
  25. public uint ExpCmdSN;
  26. public uint MaxCmdSN;
  27. public uint DataSN;
  28. public uint BufferOffset;
  29. public uint ResidualCount;
  30. public SCSIDataInPDU()
  31. {
  32. OpCode = ISCSIOpCodeName.SCSIDataIn;
  33. }
  34. public SCSIDataInPDU(byte[] buffer, int offset) : base(buffer, offset)
  35. {
  36. Acknowledge = (OpCodeSpecificHeader[0] & 0x40) != 0;
  37. ResidualOverflow = (OpCodeSpecificHeader[0] & 0x04) != 0;
  38. ResidualUnderflow = (OpCodeSpecificHeader[0] & 0x02) != 0;
  39. StatusPresent = (OpCodeSpecificHeader[0] & 0x01) != 0;
  40. Status = (SCSIStatusCodeName)OpCodeSpecificHeader[2];
  41. LUN = new LUNStructure(LUNOrOpCodeSpecific, 0);
  42. TargetTransferTag = BigEndianConverter.ToUInt32(OpCodeSpecific, 0);
  43. StatSN = BigEndianConverter.ToUInt32(OpCodeSpecific, 4);
  44. ExpCmdSN = BigEndianConverter.ToUInt32(OpCodeSpecific, 8);
  45. MaxCmdSN = BigEndianConverter.ToUInt32(OpCodeSpecific, 12);
  46. DataSN = BigEndianConverter.ToUInt32(OpCodeSpecific, 16);
  47. BufferOffset = BigEndianConverter.ToUInt32(OpCodeSpecific, 20);
  48. ResidualCount = BigEndianConverter.ToUInt32(OpCodeSpecific, 24);
  49. }
  50. public override byte[] GetBytes()
  51. {
  52. if (Acknowledge)
  53. {
  54. OpCodeSpecificHeader[0] |= 0x40;
  55. }
  56. if (ResidualOverflow)
  57. {
  58. OpCodeSpecificHeader[0] |= 0x04;
  59. }
  60. if (ResidualUnderflow)
  61. {
  62. OpCodeSpecificHeader[0] |= 0x02;
  63. }
  64. if (StatusPresent)
  65. {
  66. OpCodeSpecificHeader[0] |= 0x01;
  67. // If this bit is set to 1, the F bit MUST also be set to 1.
  68. Final = true;
  69. }
  70. OpCodeSpecificHeader[2] = (byte)Status;
  71. LUNOrOpCodeSpecific = LUN.GetBytes();
  72. BigEndianWriter.WriteUInt32(OpCodeSpecific, 0, TargetTransferTag);
  73. BigEndianWriter.WriteUInt32(OpCodeSpecific, 4, StatSN);
  74. BigEndianWriter.WriteUInt32(OpCodeSpecific, 8, ExpCmdSN);
  75. BigEndianWriter.WriteUInt32(OpCodeSpecific, 12, MaxCmdSN);
  76. BigEndianWriter.WriteUInt32(OpCodeSpecific, 16, DataSN);
  77. BigEndianWriter.WriteUInt32(OpCodeSpecific, 20, BufferOffset);
  78. BigEndianWriter.WriteUInt32(OpCodeSpecific, 24, ResidualCount);
  79. return base.GetBytes();
  80. }
  81. }
  82. }