Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ISCSI/SCSI/Enums/ModePageCodeName.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public enum ModePageCodeName : byte
ControlModePage = 0x0A,
PowerConditionModePage = 0x1A,
InformationalExceptionsControlModePage = 0x1C,
MMCapabilitiesAndMechanicalStatus = 0x2A,
Copy link
Copy Markdown
Owner

@TalAloni TalAloni Dec 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is device specific, right? which specification covers that 0x2A code?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is CD/DVD device specific (MMC), Windows requests it, for example, when peripheral device type is 0x5.
You can find it's description in scsi spec paragraph 5.2.3.4 (http://www.13thmonkey.org/documentation/SCSI/x3_304_1997.pdf)

ReturnAllPages = 0x3F,
}
}
3 changes: 3 additions & 0 deletions ISCSI/SCSI/Enums/SCSIOpCodeName.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ public enum SCSIOpCodeName : byte
ReadLong10 = 0x3E,
WriteLong10 = 0x3F,
WriteSame10 = 0x41,
ReadToc = 0x43,
ReportDensitySupport = 0x44,
GetConfiguration = 0x46,
LogSelect10 = 0x4C,
LogSense10 = 0x4D,
ReadDiscInformation = 0x51,
ModeSelect10 = 0x55,
ModeSense10 = 0x5A,
PersistentReserveIn = 0x5E,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using Utilities;

namespace SCSI
{
internal class GetConfigurationCommand : SCSICommandDescriptorBlock
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this inherit from SCSICommandDescriptorBlock10? and than you can use some of the fields...

{
public const int PacketLength = 12;
// Request Type
public byte RT;
public ushort StartingFeatureNumber;
public short AllocationLength;

public GetConfigurationCommand()
{
OpCode = SCSIOpCodeName.GetConfiguration;
}

public GetConfigurationCommand(byte[] buffer, int offset)
{
OpCode = (SCSIOpCodeName)buffer[offset + 0];
RT = (byte)(buffer[offset +1] & 0x03);
StartingFeatureNumber = BigEndianConverter.ToUInt16(buffer, offset + 2);
AllocationLength = BigEndianConverter.ToInt16(buffer, offset +7);
TransferLength = (uint)AllocationLength;
}

public override byte[] GetBytes()
{
byte[] buffer = new byte[PacketLength];
buffer[0] = (byte)OpCode;
buffer[1] = RT;
BigEndianWriter.WriteUInt16(buffer, 2, StartingFeatureNumber);
BigEndianWriter.WriteInt16(buffer, 7, AllocationLength);

return buffer;
}
}
}
46 changes: 46 additions & 0 deletions ISCSI/SCSI/SCSICommandDescriptorBlock/MMC/ReadTocCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using Utilities;

namespace SCSI
{
internal class ReadTocCommand : SCSICommandDescriptorBlock
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this inherit from SCSICommandDescriptorBlock10? and than you can use some of the fields...

{
public const int PacketLength = 12;
public bool MSF;
public byte Format;
public byte TrackSessionNumber;
public short AllocationLength;

public ReadTocCommand()
{
OpCode = SCSIOpCodeName.ReadToc;
}

public ReadTocCommand(byte[] buffer, int offset)
{
OpCode = (SCSIOpCodeName)buffer[offset + 0];
MSF = (buffer[offset + 1] & 0x02) == 1;
Format = (byte)(buffer[offset + 2] & 0xF);
TrackSessionNumber = buffer[offset + 6];
AllocationLength = BigEndianConverter.ToInt16(buffer, offset + 7);
TransferLength = (uint)AllocationLength;
Control = buffer[offset + 9];
}

public override byte[] GetBytes()
{
byte[] buffer = new byte[PacketLength];
buffer[0] = (byte)OpCode;
if (MSF)
{
buffer[1] |= 0x02;
}
buffer[2] |= (byte)(Format & 0xF);
buffer[6] = TrackSessionNumber;
BigEndianWriter.WriteInt16(buffer, 7, AllocationLength);
buffer[9] = Control;

return buffer;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* Copyright (C) 2012-2016 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
*
* You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*/
using Utilities;

namespace SCSI
{
public class ModeSense10CommandDescriptorBlock : SCSICommandDescriptorBlock
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this inherit from SCSICommandDescriptorBlock10?

{
public const int PacketLength = 10;

public bool DBD; // Disable block descriptors
public byte PC; // Page Control
public ModePageCodeName PageCode;
public byte SubpageCode;
public bool LLBA;

public ModeSense10CommandDescriptorBlock() : base()
{
OpCode = SCSIOpCodeName.ModeSense10;
}

public ModeSense10CommandDescriptorBlock(byte[] buffer, int offset) : base()
{
OpCode = (SCSIOpCodeName)buffer[offset + 0];
DBD = (buffer[offset + 1] & 0x08) != 0;
PC = (byte)(buffer[offset + 2] >> 6);
PageCode = (ModePageCodeName)(buffer[offset + 2] & 0x3F);
SubpageCode = buffer[offset + 3];
AllocationLength = BigEndianConverter.ToInt16(buffer,offset + 7);
Control = buffer[offset + 9];
}

public override byte[] GetBytes()
{
var buffer = new byte[PacketLength];
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"byte[] buffer" is better IMO

buffer[0] = (byte)OpCode;
if (DBD)
{
buffer[1] |= 0x08;
}
buffer[2] |= (byte)(PC << 6);
buffer[2] |= (byte)((byte)PageCode & 0x3F);
buffer[3] = SubpageCode;
BigEndianWriter.WriteInt16(buffer, 7, AllocationLength);
buffer[9] = Control;
return buffer;
}

public short AllocationLength
{
get
{
return (short)TransferLength;
}
set
{
TransferLength = (uint)value;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public static SCSICommandDescriptorBlock FromBytes(byte[] buffer, int offset)
return new SCSICommandDescriptorBlock6(buffer, offset);
case SCSIOpCodeName.ModeSense6:
return new ModeSense6CommandDescriptorBlock(buffer, offset);
case SCSIOpCodeName.ModeSense10:
return new ModeSense10CommandDescriptorBlock(buffer, offset);
case SCSIOpCodeName.ReadCapacity10:
return new SCSICommandDescriptorBlock10(buffer, offset);
case SCSIOpCodeName.Read10:
Expand All @@ -73,6 +75,12 @@ public static SCSICommandDescriptorBlock FromBytes(byte[] buffer, int offset)
return new SCSICommandDescriptorBlock16(buffer, offset);
case SCSIOpCodeName.ReportLUNs:
return new SCSICommandDescriptorBlock12(buffer, offset);
case SCSIOpCodeName.ReadDiscInformation:
return new SCSICommandDescriptorBlock12(buffer, offset);
case SCSIOpCodeName.ReadToc:
return new ReadTocCommand(buffer, offset);
case SCSIOpCodeName.GetConfiguration:
return new GetConfigurationCommand(buffer, offset);
default:
throw new UnsupportedSCSICommandException(String.Format("Unknown SCSI command: 0x{0}", opCode.ToString("x")));
}
Expand Down
104 changes: 104 additions & 0 deletions ISCSI/SCSI/SCSIReturnParameters/MMC/FormattedToc.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Text;
using Utilities;

namespace SCSI
{
internal class FormattedToc
{
const int Length = 64;
byte[] data = new byte[Length];
bool _msf = false;

/// <summary>
/// The TOC data length indicates the length in bytes of the following TOC data. The TOC data length value
/// does not include the TOC data length field itself.This value is not modified when the allocation length is
/// insufficient to return all of the TOC data available.
/// </summary>
private ushort TocDataLength
{
get { return BigEndianConverter.ToUInt16(data, 0); }
set { BigEndianWriter.WriteUInt16(data, 0, value); }
}

/// <summary>
/// The First Track Number field indicates the first track number in the first complete session Table of Contents.
/// </summary>
public byte FirstTrackNumber
{
get { return data[2]; }
set { data[2] = value; }
}

/// <summary>
/// The Last Track Number field indicates the last track number in the last complete session Table of Contents
/// before the lead-out.
/// </summary>
public byte LastTrackNumber
{
get { return data[3]; }
set { data[3] = value; }
}

/// <summary>
/// An MSF bit of zero indicates that the Logical Block Address field
/// contains a logical block address.An MSF bit of one indicates the Logical Block Address field contains an
/// MSF address.
/// </summary>
/// <param name="msf"></param>
public FormattedToc(bool msf)
{
_msf = msf;
}

/// <summary>
/// Sets TOC Track Descriptor in the Formatted TOC data array.
/// </summary>
/// <param name="position">Descriptor position in the data array</param>
/// <param name="adr">The ADR field gives the type of information encoded in the Q sub-channel of the block where this TOC
/// entry was found.</param>
/// <param name="control">The Control Field indicates the attributes, of the track.</param>
/// <param name="trackNumber">The Track Number field indicates the track number for which the data in the TOC track descriptor is valid.
/// A track number of AAh indicates that the track descriptor is for the start of the lead-out area.</param>
/// <param name="address">The Logical Block Address contains the address of the first block with user information for that track
/// number as read from the Table of Contents.</param>
public void SetTocTrackDescriptor(byte position, byte adr, byte control, byte trackNumber, uint address)
{
int offset = 4 + position * 8; // 4 descriptor start offset, 8 - size of descriptor (TOC/PMA/ATIP Response Data Format 0000)
// Reserved
data[offset + 0] = 0;
// ADR(7-4) CONTROL(3-0)
data[offset + 1] = (byte)(adr << 4 | (control & 0xF));
data[offset + 2] = trackNumber;
// Reserved
data[offset + 3] = 0;

/* Track Start Address */
if (_msf)
{
BigEndianWriter.WriteUInt32(data, offset + 4, MmcHelper.Lba2Msf(address));
}
else
{
BigEndianWriter.WriteUInt32(data, offset + 4, address);
}
}

/// <summary>
/// Adjusts data length for requested track count.
/// </summary>
/// <param name="trackCount"></param>
/// <exception cref="NotImplementedException"></exception>
public void UpdateDataLength(int trackCount)
{
// 4 bytes of data + trackCount descriptors - TOC data length field itself
TocDataLength = (byte)(4 + trackCount * 8 - 2);
}

public byte[] GetBytes()
{
return data;
}
}
}
Loading