private void InterceptModeSense6(LogicalUnit logicalUnit, byte[] commandBytes, byte[] response) { ModeParameterHeader6 header = new ModeParameterHeader6(response, 0); if (header.BlockDescriptorLength == ShortLBAModeParameterBlockDescriptor.Length) { ShortLBAModeParameterBlockDescriptor descriptor = new ShortLBAModeParameterBlockDescriptor(response, ModeParameterHeader6.Length); logicalUnit.BlockSize = descriptor.LogicalBlockLength; Log(Severity.Verbose, "LUN: {0}, BlockSize updated to {1}", logicalUnit.AssociatedLun, logicalUnit.BlockSize); } }
public SCSIStatusCodeName ModeSense6(ModeSense6CommandDescriptorBlock command, LUNStructure lun, out byte[] response) { if (lun >= m_disks.Count) { response = FormatSenseData(SenseDataParameter.GetIllegalRequestInvalidLUNSenseData()); return(SCSIStatusCodeName.CheckCondition); } ISCSIServer.Log("[ModeSense6] Page code: 0x{0}, Sub page code: 0x{1}", command.PageCode.ToString("X"), command.SubpageCode.ToString("X")); byte[] pageData; switch ((ModePageCodeName)command.PageCode) { case ModePageCodeName.CachingParametersPage: { CachingParametersPage page = new CachingParametersPage(); page.RCD = true; pageData = page.GetBytes(); break; } case ModePageCodeName.ControlModePage: { ControlModePage page = new ControlModePage(); pageData = page.GetBytes(); break; } case ModePageCodeName.PowerConditionModePage: { if (command.SubpageCode == 0x00) { PowerConditionModePage page = new PowerConditionModePage(); pageData = page.GetBytes(); break; } else if (command.SubpageCode == 0x01) { PowerConsumptionModePage page = new PowerConsumptionModePage(); pageData = page.GetBytes(); break; } else { response = FormatSenseData(SenseDataParameter.GetIllegalRequestInvalidFieldInCDBSenseData()); ISCSIServer.Log("[ModeSense6] Power condition subpage 0x{0} is not implemented", command.SubpageCode.ToString("x")); return(SCSIStatusCodeName.CheckCondition); } } case ModePageCodeName.InformationalExceptionsControlModePage: { InformationalExceptionsControlModePage page = new InformationalExceptionsControlModePage(); pageData = page.GetBytes(); break; } case ModePageCodeName.ReturnAllPages: { CachingParametersPage page1 = new CachingParametersPage(); page1.RCD = true; InformationalExceptionsControlModePage page2 = new InformationalExceptionsControlModePage(); pageData = new byte[page1.Length + page2.Length]; Array.Copy(page1.GetBytes(), pageData, page1.Length); Array.Copy(page2.GetBytes(), 0, pageData, page1.Length, page2.Length); break; } case ModePageCodeName.VendorSpecificPage: { // Microsoft iSCSI Target running under Windows 2000 will request this page, we immitate Microsoft iSCSI Target by sending back an empty page VendorSpecificPage page = new VendorSpecificPage(); pageData = page.GetBytes(); break; } default: { response = FormatSenseData(SenseDataParameter.GetIllegalRequestInvalidFieldInCDBSenseData()); ISCSIServer.Log("[ModeSense6] ModeSense6 page 0x{0} is not implemented", command.PageCode.ToString("x")); return(SCSIStatusCodeName.CheckCondition); } } ModeParameterHeader6 header = new ModeParameterHeader6(); header.WP = m_disks[lun].IsReadOnly; // Write protected, even when set to true, Windows does not always prevent the disk from being written to. header.DPOFUA = true; // Microsoft iSCSI Target support this byte[] descriptorBytes = new byte[0]; if (!command.DBD) { ShortLBAModeParameterBlockDescriptor descriptor = new ShortLBAModeParameterBlockDescriptor(); descriptor.LogicalBlockLength = (uint)m_disks[lun].BytesPerSector; descriptorBytes = descriptor.GetBytes(); } header.BlockDescriptorLength = (byte)descriptorBytes.Length; header.ModeDataLength += (byte)(descriptorBytes.Length + pageData.Length); response = new byte[1 + header.ModeDataLength]; Array.Copy(header.GetBytes(), 0, response, 0, header.Length); Array.Copy(descriptorBytes, 0, response, header.Length, descriptorBytes.Length); Array.Copy(pageData, 0, response, header.Length + descriptorBytes.Length, pageData.Length); return(SCSIStatusCodeName.Good); }