public byte[] GetBytes(ScsiCommand cmd, byte[] immediateData, int offset, int count, bool isFinalData, bool willRead, bool willWrite, uint expected) { BasicHeaderSegment _basicHeader = new BasicHeaderSegment(); _basicHeader.Immediate = cmd.ImmediateDelivery; _basicHeader.OpCode = OpCode.ScsiCommand; _basicHeader.FinalPdu = isFinalData; _basicHeader.TotalAhsLength = 0; _basicHeader.DataSegmentLength = count; _basicHeader.InitiatorTaskTag = _connection.Session.CurrentTaskTag; byte[] buffer = new byte[48 + Utilities.RoundUp(count, 4)]; _basicHeader.WriteTo(buffer, 0); buffer[1] = PackAttrByte(isFinalData, willRead, willWrite, cmd.TaskAttributes); Utilities.WriteBytesBigEndian(_lun, buffer, 8); Utilities.WriteBytesBigEndian(expected, buffer, 20); Utilities.WriteBytesBigEndian(_connection.Session.CommandSequenceNumber, buffer, 24); Utilities.WriteBytesBigEndian(_connection.ExpectedStatusSequenceNumber, buffer, 28); cmd.WriteTo(buffer, 32); if (immediateData != null && count != 0) { Array.Copy(immediateData, offset, buffer, 48, count); } return buffer; }
public byte[] GetBytes(ScsiCommand cmd, byte[] immediateData, int offset, int count, bool isFinalData, bool willRead, bool willWrite, uint expected) { BasicHeaderSegment _basicHeader = new BasicHeaderSegment(); _basicHeader.Immediate = cmd.ImmediateDelivery; _basicHeader.OpCode = OpCode.ScsiCommand; _basicHeader.FinalPdu = isFinalData; _basicHeader.TotalAhsLength = 0; _basicHeader.DataSegmentLength = count; _basicHeader.InitiatorTaskTag = _connection.Session.CurrentTaskTag; byte[] buffer = new byte[48 + Utilities.RoundUp(count, 4)]; _basicHeader.WriteTo(buffer, 0); buffer[1] = PackAttrByte(isFinalData, willRead, willWrite, cmd.TaskAttributes); Utilities.WriteBytesBigEndian(_lun, buffer, 8); Utilities.WriteBytesBigEndian(expected, buffer, 20); Utilities.WriteBytesBigEndian(_connection.Session.CommandSequenceNumber, buffer, 24); Utilities.WriteBytesBigEndian(_connection.ExpectedStatusSequenceNumber, buffer, 28); cmd.WriteTo(buffer, 32); if (immediateData != null && count != 0) { Array.Copy(immediateData, offset, buffer, 48, count); } return(buffer); }
public T Send <T>(ScsiCommand cmd, byte[] buffer, int offset, int count, int expected) where T : ScsiResponse, new() { byte[] tempBuffer = new byte[expected]; int numRead = Send(cmd, buffer, offset, count, tempBuffer, 0, expected); T result = new T(); result.ReadFrom(tempBuffer, 0, numRead); return(result); }
/// <summary> /// Sends an SCSI command (aka task) to a LUN via the connected target. /// </summary> /// <param name="cmd">The command to send.</param> /// <param name="outBuffer">The data to send with the command.</param> /// <param name="outBufferOffset">The offset of the first byte to send.</param> /// <param name="outBufferCount">The number of bytes to send, if any.</param> /// <param name="inBuffer">The buffer to fill with returned data.</param> /// <param name="inBufferOffset">The first byte to fill with returned data.</param> /// <param name="inBufferMax">The maximum amount of data to receive.</param> /// <returns>The number of bytes received.</returns> public int Send(ScsiCommand cmd, byte[] outBuffer, int outBufferOffset, int outBufferCount, byte[] inBuffer, int inBufferOffset, int inBufferMax) { CommandRequest req = new CommandRequest(this, cmd.TargetLun); int toSend = Math.Min(Math.Min(outBufferCount, Session.ImmediateData ? Session.FirstBurstLength : 0), MaxTargetReceiveDataSegmentLength); byte[] packet = req.GetBytes(cmd, outBuffer, outBufferOffset, toSend, true, inBufferMax != 0, outBufferCount != 0, (uint)(outBufferCount != 0 ? outBufferCount : inBufferMax)); _stream.Write(packet, 0, packet.Length); _stream.Flush(); int numApproved = 0; int numSent = toSend; int pktsSent = 0; while (numSent < outBufferCount) { ProtocolDataUnit pdu = ReadPdu(); ReadyToTransferPacket resp = ParseResponse <ReadyToTransferPacket>(pdu); numApproved = (int)resp.DesiredTransferLength; uint targetTransferTag = resp.TargetTransferTag; while (numApproved > 0) { toSend = Math.Min(Math.Min(outBufferCount - numSent, numApproved), MaxTargetReceiveDataSegmentLength); DataOutPacket pkt = new DataOutPacket(this, cmd.TargetLun); packet = pkt.GetBytes(outBuffer, outBufferOffset + numSent, toSend, toSend == numApproved, pktsSent++, (uint)numSent, targetTransferTag); _stream.Write(packet, 0, packet.Length); _stream.Flush(); numApproved -= toSend; numSent += toSend; } } bool isFinal = false; int numRead = 0; while (!isFinal) { ProtocolDataUnit pdu = ReadPdu(); if (pdu.OpCode == OpCode.ScsiResponse) { Response resp = ParseResponse <Response>(pdu); if (resp.StatusPresent && resp.Status == ScsiStatus.CheckCondition) { ushort senseLength = EndianUtilities.ToUInt16BigEndian(pdu.ContentData, 0); byte[] senseData = new byte[senseLength]; Array.Copy(pdu.ContentData, 2, senseData, 0, senseLength); throw new ScsiCommandException(resp.Status, "Target indicated SCSI failure", senseData); } if (resp.StatusPresent && resp.Status != ScsiStatus.Good) { throw new ScsiCommandException(resp.Status, "Target indicated SCSI failure"); } isFinal = resp.Header.FinalPdu; } else if (pdu.OpCode == OpCode.ScsiDataIn) { DataInPacket resp = ParseResponse <DataInPacket>(pdu); if (resp.StatusPresent && resp.Status != ScsiStatus.Good) { throw new ScsiCommandException(resp.Status, "Target indicated SCSI failure"); } if (resp.ReadData != null) { Array.Copy(resp.ReadData, 0, inBuffer, (int)(inBufferOffset + resp.BufferOffset), resp.ReadData.Length); numRead += resp.ReadData.Length; } isFinal = resp.Header.FinalPdu; } } Session.NextTaskTag(); Session.NextCommandSequenceNumber(); return(numRead); }
private T Send <T>(ScsiCommand cmd, byte[] buffer, int offset, int count, int expected) where T : ScsiResponse, new() { return(_currentConnection.Send <T>(cmd, buffer, offset, count, expected)); }
/// <summary> /// Sends an SCSI command (aka task) to a LUN via the connected target. /// </summary> /// <param name="cmd">The command to send.</param> /// <param name="outBuffer">The data to send with the command.</param> /// <param name="outBufferOffset">The offset of the first byte to send.</param> /// <param name="outBufferCount">The number of bytes to send, if any.</param> /// <param name="inBuffer">The buffer to fill with returned data.</param> /// <param name="inBufferOffset">The first byte to fill with returned data.</param> /// <param name="inBufferMax">The maximum amount of data to receive.</param> /// <returns>The number of bytes received.</returns> private int Send(ScsiCommand cmd, byte[] outBuffer, int outBufferOffset, int outBufferCount, byte[] inBuffer, int inBufferOffset, int inBufferMax) { return(_currentConnection.Send(cmd, outBuffer, outBufferOffset, outBufferCount, inBuffer, inBufferOffset, inBufferMax)); }