public void Target_OnDeviceIdentificationInquiry(object sender, DeviceIdentificationInquiryEventArgs args) { // ISCSI identifier is needed for WinPE to pick up the disk during boot (after iPXE's sanhook) args.Page.IdentificationDescriptorList.Add(IdentificationDescriptor.GetSCSINameStringIdentifier(m_targetName)); // To be thread-safe we must capture the delegate reference first EventHandler <DeviceIdentificationInquiryEventArgs> handler = OnDeviceIdentificationInquiry; if (handler != null) { handler(this, args); } }
public SCSIStatusCodeName Inquiry(InquiryCommand command, LUNStructure lun, out byte[] response) { if (lun >= m_disks.Count) { response = FormatSenseData(SenseDataParameter.GetIllegalRequestInvalidLUNSenseData()); return(SCSIStatusCodeName.CheckCondition); } if (!command.EVPD) { if ((int)command.PageCode == 0) { StandardInquiryData inquiryData = new StandardInquiryData(); inquiryData.PeripheralDeviceType = 0; // Direct access block device inquiryData.VendorIdentification = "TalAloni"; inquiryData.ProductIdentification = "iSCSI Disk " + ((ushort)lun).ToString(); inquiryData.ProductRevisionLevel = "1.00"; inquiryData.DriveSerialNumber = 0; inquiryData.CmdQue = true; inquiryData.Version = 5; // Microsoft iSCSI Target report version 5 if (this is ISCSITarget) { inquiryData.VersionDescriptors.Add(0x0960); // iSCSI } response = inquiryData.GetBytes(); } else { ISCSIServer.Log("[Inquiry] Invalid request"); response = FormatSenseData(SenseDataParameter.GetIllegalRequestInvalidFieldInCDBSenseData()); return(SCSIStatusCodeName.CheckCondition); } } else { ISCSIServer.Log("[Inquiry] Page code: 0x{0}", command.PageCode.ToString("X")); switch (command.PageCode) { case VitalProductDataPageName.SupportedVPDPages: { SupportedVitaLProductDataPages page = new SupportedVitaLProductDataPages(); page.SupportedPageList.Add((byte)VitalProductDataPageName.SupportedVPDPages); page.SupportedPageList.Add((byte)VitalProductDataPageName.UnitSerialNumber); page.SupportedPageList.Add((byte)VitalProductDataPageName.DeviceIdentification); response = page.GetBytes(); break; } case VitalProductDataPageName.UnitSerialNumber: { UnitSerialNumberVPDPage page = new UnitSerialNumberVPDPage(); // Older products that only support the Product Serial Number parameter will have a page length of 08h, while newer products that support both parameters (Vendor Unique field from the StandardInquiryData) will have a page length of 14h // Microsoft iSCSI Target uses values such as "34E5A6FC-3ACC-452D-AEDA-6EE2EFF20FB4" ulong serialNumber = 0; page.ProductSerialNumber = serialNumber.ToString("00000000"); response = page.GetBytes(); break; } case VitalProductDataPageName.DeviceIdentification: { DeviceIdentificationVPDPage page = new DeviceIdentificationVPDPage(); // NAA identifier is needed to prevent 0xF4 BSOD during Windows setup page.IdentificationDescriptorList.Add(IdentificationDescriptor.GetNAAExtendedIdentifier(5, lun)); if (this is ISCSITarget) { // ISCSI identifier is needed for WinPE to pick up the disk during boot (after iPXE's sanhook) page.IdentificationDescriptorList.Add(IdentificationDescriptor.GetSCSINameStringIdentifier(((ISCSITarget)this).TargetName)); } response = page.GetBytes(); break; } case VitalProductDataPageName.BlockLimits: { /* Provide only when requeste explicitly */ BlockLimitsVPDPage page = new BlockLimitsVPDPage(); page.OptimalTransferLengthGranularity = 128; page.MaximumTransferLength = (uint)DiskAccessLibrary.Settings.MaximumTransferSizeLBA; page.OptimalTransferLength = 128; response = page.GetBytes(); break; } case VitalProductDataPageName.BlockDeviceCharacteristics: { /* Provide only when requeste explicitly */ BlockDeviceCharacteristicsVPDPage page = new BlockDeviceCharacteristicsVPDPage(); page.MediumRotationRate = 0; // Not reported response = page.GetBytes(); break; } default: { response = FormatSenseData(SenseDataParameter.GetIllegalRequestInvalidFieldInCDBSenseData()); ISCSIServer.Log("[Inquiry] Unsupported VPD Page request (0x{0})", command.PageCode.ToString("X")); return(SCSIStatusCodeName.CheckCondition); } } } // we must not return more bytes than InquiryCommand.AllocationLength if (response.Length > command.AllocationLength) { response = ByteReader.ReadBytes(response, 0, command.AllocationLength); } return(SCSIStatusCodeName.Good); }