SCSIResponsePDU.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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. public class SCSIResponsePDU : ISCSIPDU
  15. {
  16. public bool BidirectionalReadResidualOverflow;
  17. public bool BidirectionalReadResidualUnderflow;
  18. public bool ResidualOverflow;
  19. public bool ResidualUnderflow;
  20. public ISCSIResponseName Response;
  21. public SCSIStatusCodeName Status;
  22. public uint SNACKTag;
  23. public uint StatSN;
  24. public uint ExpCmdSN;
  25. public uint MaxCmdSN;
  26. public uint ExpDataSN;
  27. public uint BidirectionalReadResidualCount;
  28. public uint ResidualCount;
  29. public SCSIResponsePDU() : base()
  30. {
  31. OpCode = ISCSIOpCodeName.SCSIResponse;
  32. Final = true;
  33. }
  34. public SCSIResponsePDU(byte[] buffer) : base(buffer)
  35. {
  36. BidirectionalReadResidualOverflow = (OpCodeSpecificHeader[0] & 0x10) != 0;
  37. BidirectionalReadResidualUnderflow = (OpCodeSpecificHeader[0] & 0x08) != 0;
  38. ResidualOverflow = (OpCodeSpecificHeader[0] & 0x04) != 0;
  39. ResidualUnderflow = (OpCodeSpecificHeader[0] & 0x02) != 0;
  40. Response = (ISCSIResponseName)OpCodeSpecificHeader[1];
  41. Status = (SCSIStatusCodeName)OpCodeSpecificHeader[2];
  42. SNACKTag = BigEndianConverter.ToUInt32(OpCodeSpecific, 0);
  43. StatSN = BigEndianConverter.ToUInt32(OpCodeSpecific, 4);
  44. ExpCmdSN = BigEndianConverter.ToUInt32(OpCodeSpecific, 8);
  45. MaxCmdSN = BigEndianConverter.ToUInt32(OpCodeSpecific, 12);
  46. ExpDataSN = BigEndianConverter.ToUInt32(OpCodeSpecific, 16);
  47. BidirectionalReadResidualCount = BigEndianConverter.ToUInt32(OpCodeSpecific, 20);
  48. ResidualCount = BigEndianConverter.ToUInt32(OpCodeSpecific, 24);
  49. }
  50. public override byte[] GetBytes()
  51. {
  52. if (BidirectionalReadResidualOverflow)
  53. {
  54. OpCodeSpecificHeader[0] |= 0x10;
  55. }
  56. if (BidirectionalReadResidualUnderflow)
  57. {
  58. OpCodeSpecificHeader[0] |= 0x08;
  59. }
  60. if (ResidualOverflow)
  61. {
  62. OpCodeSpecificHeader[0] |= 0x04;
  63. }
  64. if (ResidualUnderflow)
  65. {
  66. OpCodeSpecificHeader[0] |= 0x02;
  67. }
  68. OpCodeSpecificHeader[1] = (byte)Response;
  69. OpCodeSpecificHeader[2] = (byte)Status;
  70. Array.Copy(BigEndianConverter.GetBytes(SNACKTag), 0, OpCodeSpecific, 0, 4);
  71. Array.Copy(BigEndianConverter.GetBytes(StatSN), 0, OpCodeSpecific, 4, 4);
  72. Array.Copy(BigEndianConverter.GetBytes(ExpCmdSN), 0, OpCodeSpecific, 8, 4);
  73. Array.Copy(BigEndianConverter.GetBytes(MaxCmdSN), 0, OpCodeSpecific, 12, 4);
  74. Array.Copy(BigEndianConverter.GetBytes(ExpDataSN), 0, OpCodeSpecific, 16, 4);
  75. Array.Copy(BigEndianConverter.GetBytes(BidirectionalReadResidualCount), 0, OpCodeSpecific, 20, 4);
  76. Array.Copy(BigEndianConverter.GetBytes(ResidualCount), 0, OpCodeSpecific, 24, 4);
  77. return base.GetBytes();
  78. }
  79. }
  80. }