public Scsi ReportScsiInquiry() { DicConsole.WriteLine("Querying SCSI INQUIRY..."); bool sense = _dev.ScsiInquiry(out byte[] buffer, out byte[] senseBuffer); var report = new Scsi(); if (sense) { return(null); } Inquiry?decodedNullable = Inquiry.Decode(buffer); if (!decodedNullable.HasValue) { return(null); } Inquiry decoded = decodedNullable.Value; // Clear Seagate serial number if (decoded.SeagatePresent && StringHandlers.CToString(decoded.VendorIdentification)?.Trim().ToLowerInvariant() == "seagate") { for (int i = 36; i <= 43; i++) { buffer[i] = 0; } } report.InquiryData = buffer; return(report); }
public DeviceInfo(Device dev) { Type = dev.Type; Manufacturer = dev.Manufacturer; Model = dev.Model; FirmwareRevision = dev.FirmwareRevision; Serial = dev.Serial; ScsiType = dev.ScsiType; IsRemovable = dev.IsRemovable; IsUsb = dev.IsUsb; UsbVendorId = dev.UsbVendorId; UsbProductId = dev.UsbProductId; UsbDescriptors = dev.UsbDescriptors; UsbManufacturerString = dev.UsbManufacturerString; UsbProductString = dev.UsbProductString; UsbSerialString = dev.UsbSerialString; IsFireWire = dev.IsFireWire; FireWireGuid = dev.FireWireGuid; FireWireModel = dev.FireWireModel; FireWireModelName = dev.FireWireModelName; FireWireVendor = dev.FireWireVendor; FireWireVendorName = dev.FireWireVendorName; IsCompactFlash = dev.IsCompactFlash; IsPcmcia = dev.IsPcmcia; Cis = dev.Cis; switch (dev.Type) { case DeviceType.ATA: { bool sense = dev.AtaIdentify(out byte[] ataBuf, out AtaErrorRegistersChs errorRegisters); if (sense) { DicConsole.DebugWriteLine("Device-Info command", "STATUS = 0x{0:X2}", errorRegisters.Status); DicConsole.DebugWriteLine("Device-Info command", "ERROR = 0x{0:X2}", errorRegisters.Error); DicConsole.DebugWriteLine("Device-Info command", "NSECTOR = 0x{0:X2}", errorRegisters.SectorCount); DicConsole.DebugWriteLine("Device-Info command", "SECTOR = 0x{0:X2}", errorRegisters.Sector); DicConsole.DebugWriteLine("Device-Info command", "CYLHIGH = 0x{0:X2}", errorRegisters.CylinderHigh); DicConsole.DebugWriteLine("Device-Info command", "CYLLOW = 0x{0:X2}", errorRegisters.CylinderLow); DicConsole.DebugWriteLine("Device-Info command", "DEVICE = 0x{0:X2}", errorRegisters.DeviceHead); DicConsole.DebugWriteLine("Device-Info command", "Error code = {0}", dev.LastError); break; } if (dev.Error) { DicConsole.ErrorWriteLine("Error {0} querying ATA IDENTIFY", dev.LastError); break; } AtaIdentify = ataBuf; dev.EnableMediaCardPassThrough(out errorRegisters, dev.Timeout, out _); if (errorRegisters.Sector == 0xAA && errorRegisters.SectorCount == 0x55) { AtaMcptError = errorRegisters; } break; } case DeviceType.ATAPI: { bool sense = dev.AtapiIdentify(out byte[] ataBuf, out AtaErrorRegistersChs errorRegisters); if (sense) { DicConsole.DebugWriteLine("Device-Info command", "STATUS = 0x{0:X2}", errorRegisters.Status); DicConsole.DebugWriteLine("Device-Info command", "ERROR = 0x{0:X2}", errorRegisters.Error); DicConsole.DebugWriteLine("Device-Info command", "NSECTOR = 0x{0:X2}", errorRegisters.SectorCount); DicConsole.DebugWriteLine("Device-Info command", "SECTOR = 0x{0:X2}", errorRegisters.Sector); DicConsole.DebugWriteLine("Device-Info command", "CYLHIGH = 0x{0:X2}", errorRegisters.CylinderHigh); DicConsole.DebugWriteLine("Device-Info command", "CYLLOW = 0x{0:X2}", errorRegisters.CylinderLow); DicConsole.DebugWriteLine("Device-Info command", "DEVICE = 0x{0:X2}", errorRegisters.DeviceHead); DicConsole.DebugWriteLine("Device-Info command", "Error code = {0}", dev.LastError); break; } if (!dev.Error) { AtapiIdentify = ataBuf; } else { DicConsole.ErrorWriteLine("Error {0} querying ATA PACKET IDENTIFY", dev.LastError); } // ATAPI devices are also SCSI devices goto case DeviceType.SCSI; } case DeviceType.SCSI: { bool sense = dev.ScsiInquiry(out byte[] inqBuf, out byte[] senseBuf); if (sense) { DicConsole.ErrorWriteLine("SCSI error:\n{0}", Sense.PrettifySense(senseBuf)); break; } ScsiInquiryData = inqBuf; ScsiInquiry = Inquiry.Decode(inqBuf); sense = dev.ScsiInquiry(out inqBuf, out senseBuf, 0x00); if (!sense) { ScsiEvpdPages = new Dictionary <byte, byte[]>(); byte[] pages = EVPD.DecodePage00(inqBuf); if (pages != null) { foreach (byte page in pages) { sense = dev.ScsiInquiry(out inqBuf, out senseBuf, page); if (sense) { continue; } ScsiEvpdPages.Add(page, inqBuf); } } } var devType = (PeripheralDeviceTypes)ScsiInquiry.Value.PeripheralDeviceType; sense = dev.ModeSense10(out byte[] modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out _); if (!sense && !dev.Error) { ScsiModeSense10 = modeBuf; } if (sense || dev.Error) { sense = dev.ModeSense10(out modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out _); if (!sense && !dev.Error) { ScsiModeSense10 = modeBuf; } } if (!sense && !dev.Error) { ScsiMode = Modes.DecodeMode10(modeBuf, devType); } bool useMode10 = !(sense || dev.Error || !ScsiMode.HasValue); sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out _); if (!sense && !dev.Error) { ScsiModeSense6 = modeBuf; } if (sense || dev.Error) { sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out _); if (!sense && !dev.Error) { ScsiModeSense6 = modeBuf; } } if (sense || dev.Error) { sense = dev.ModeSense(out modeBuf, out senseBuf, 5, out _); if (!sense && !dev.Error) { ScsiModeSense6 = modeBuf; } } if (!sense && !dev.Error && !useMode10) { ScsiMode = Modes.DecodeMode6(modeBuf, devType); } switch (devType) { case PeripheralDeviceTypes.MultiMediaDevice: { sense = dev.GetConfiguration(out byte[] confBuf, out senseBuf, dev.Timeout, out _); if (!sense) { MmcConfiguration = confBuf; } // TODO: DVD drives respond correctly to BD status. // While specification says if no medium is present // it should inform all possible capabilities, // testing drives show only supported media capabilities. /* * byte[] strBuf; * sense = dev.ReadDiscStructure(out strBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.CapabilityList, 0, dev.Timeout, out _); * * if (!sense) * { * Decoders.SCSI.DiscStructureCapabilities.Capability[] caps = Decoders.SCSI.DiscStructureCapabilities.Decode(strBuf); * if (caps != null) * { * foreach (Decoders.SCSI.DiscStructureCapabilities.Capability cap in caps) * { * if (cap.SDS && cap.RDS) * DicConsole.WriteLine("Drive can READ/SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode); * else if (cap.SDS) * DicConsole.WriteLine("Drive can SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode); * else if (cap.RDS) * DicConsole.WriteLine("Drive can READ DISC STRUCTURE format {0:X2}h", cap.FormatCode); * } * } * } * * sense = dev.ReadDiscStructure(out strBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.CapabilityList, 0, dev.Timeout, out _); * * if (!sense) * { * Decoders.SCSI.DiscStructureCapabilities.Capability[] caps = Decoders.SCSI.DiscStructureCapabilities.Decode(strBuf); * if (caps != null) * { * foreach (Decoders.SCSI.DiscStructureCapabilities.Capability cap in caps) * { * if (cap.SDS && cap.RDS) * DicConsole.WriteLine("Drive can READ/SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode); * else if (cap.SDS) * DicConsole.WriteLine("Drive can SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode); * else if (cap.RDS) * DicConsole.WriteLine("Drive can READ DISC STRUCTURE format {0:X2}h", cap.FormatCode); * } * } * } */ #region Plextor if (dev.Manufacturer == "PLEXTOR") { bool plxtSense = true; bool plxtDvd = false; byte[] plxtBuf = null; switch (dev.Model) { case "DVDR PX-708A": case "DVDR PX-708A2": case "DVDR PX-712A": plxtDvd = true; plxtSense = dev.PlextorReadEeprom(out plxtBuf, out senseBuf, dev.Timeout, out _); break; case "DVDR PX-714A": case "DVDR PX-716A": case "DVDR PX-716AL": case "DVDR PX-755A": case "DVDR PX-760A": { plxtBuf = new byte[256 * 4]; for (byte i = 0; i < 4; i++) { plxtSense = dev.PlextorReadEepromBlock(out byte[] plxtBufSmall, out senseBuf, i, 256, dev.Timeout, out _); if (plxtSense) { break; } Array.Copy(plxtBufSmall, 0, plxtBuf, i * 256, 256); } plxtDvd = true; break; } default: { if (dev.Model.StartsWith("CD-R ", StringComparison.Ordinal)) { plxtSense = dev.PlextorReadEepromCdr(out plxtBuf, out senseBuf, dev.Timeout, out _); } break; } } PlextorFeatures = new Plextor { IsDvd = plxtDvd }; if (!plxtSense) { PlextorFeatures.Eeprom = plxtBuf; if (plxtDvd) { PlextorFeatures.Discs = BigEndianBitConverter.ToUInt16(plxtBuf, 0x0120); PlextorFeatures.CdReadTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x0122); PlextorFeatures.CdWriteTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x0126); PlextorFeatures.DvdReadTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x012A); PlextorFeatures.DvdWriteTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x012E); } else { PlextorFeatures.Discs = BigEndianBitConverter.ToUInt16(plxtBuf, 0x0078); PlextorFeatures.CdReadTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x006C); PlextorFeatures.CdWriteTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x007A); } } plxtSense = dev.PlextorGetPoweRec(out senseBuf, out bool plxtPwrRecEnabled, out ushort plxtPwrRecSpeed, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.PoweRec = true; if (plxtPwrRecEnabled) { PlextorFeatures.PoweRecEnabled = true; PlextorFeatures.PoweRecRecommendedSpeed = plxtPwrRecSpeed; plxtSense = dev.PlextorGetSpeeds(out senseBuf, out ushort plxtPwrRecSelected, out ushort plxtPwrRecMax, out ushort plxtPwrRecLast, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.PoweRecSelected = plxtPwrRecSelected; PlextorFeatures.PoweRecMax = plxtPwrRecMax; PlextorFeatures.PoweRecLast = plxtPwrRecLast; } } } // TODO: Check it with a drive plxtSense = dev.PlextorGetSilentMode(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { if (plxtBuf[0] == 1) { PlextorFeatures.SilentModeEnabled = true; PlextorFeatures.AccessTimeLimit = plxtBuf[1]; PlextorFeatures.CdReadSpeedLimit = plxtBuf[2]; PlextorFeatures.DvdReadSpeedLimit = plxtBuf[3]; PlextorFeatures.CdWriteSpeedLimit = plxtBuf[4]; // TODO: Check which one is each one /* * if(plxtBuf[6] > 0) * DicConsole.WriteLine("\tTray eject speed limited to {0}", * -(plxtBuf[6] + 48)); * if(plxtBuf[7] > 0) * DicConsole.WriteLine("\tTray eject speed limited to {0}", * plxtBuf[7] - 47); */ } } plxtSense = dev.PlextorGetGigaRec(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.GigaRec = true; } plxtSense = dev.PlextorGetSecuRec(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.SecuRec = true; } plxtSense = dev.PlextorGetSpeedRead(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.SpeedRead = true; if ((plxtBuf[2] & 0x01) == 0x01) { PlextorFeatures.SpeedReadEnabled = true; } } plxtSense = dev.PlextorGetHiding(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.Hiding = true; if ((plxtBuf[2] & 0x02) == 0x02) { PlextorFeatures.HidesRecordables = true; } if ((plxtBuf[2] & 0x01) == 0x01) { PlextorFeatures.HidesSessions = true; } } plxtSense = dev.PlextorGetVariRec(out plxtBuf, out senseBuf, false, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.VariRec = true; } if (plxtDvd) { plxtSense = dev.PlextorGetVariRec(out plxtBuf, out senseBuf, true, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.VariRecDvd = true; } plxtSense = dev.PlextorGetBitsetting(out plxtBuf, out senseBuf, false, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.BitSetting = true; } plxtSense = dev.PlextorGetBitsetting(out plxtBuf, out senseBuf, true, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.BitSettingDl = true; } plxtSense = dev.PlextorGetTestWriteDvdPlus(out plxtBuf, out senseBuf, dev.Timeout, out _); if (!plxtSense) { PlextorFeatures.DvdPlusWriteTest = true; } } } #endregion Plextor if (ScsiInquiry.Value.KreonPresent) { if (!dev.KreonGetFeatureList(out senseBuf, out KreonFeatures krFeatures, dev.Timeout, out _)) { KreonFeatures = krFeatures; } } break; } case PeripheralDeviceTypes.SequentialAccess: { sense = dev.ReadBlockLimits(out byte[] seqBuf, out senseBuf, dev.Timeout, out _); if (sense) { DicConsole.ErrorWriteLine("READ BLOCK LIMITS:\n{0}", Sense.PrettifySense(senseBuf)); } else { BlockLimits = seqBuf; } sense = dev.ReportDensitySupport(out seqBuf, out senseBuf, dev.Timeout, out _); if (sense) { DicConsole.ErrorWriteLine("REPORT DENSITY SUPPORT:\n{0}", Sense.PrettifySense(senseBuf)); } else { DensitySupport = seqBuf; DensitySupportHeader = Decoders.SCSI.SSC.DensitySupport.DecodeDensity(seqBuf); } sense = dev.ReportDensitySupport(out seqBuf, out senseBuf, true, false, dev.Timeout, out _); if (sense) { DicConsole.ErrorWriteLine("REPORT DENSITY SUPPORT (MEDIUM):\n{0}", Sense.PrettifySense(senseBuf)); } else { MediumDensitySupport = seqBuf; MediaTypeSupportHeader = Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(seqBuf); } break; } } break; } case DeviceType.MMC: { bool sense = dev.ReadCid(out byte[] mmcBuf, out _, dev.Timeout, out _); if (!sense) { CID = mmcBuf; } sense = dev.ReadCsd(out mmcBuf, out _, dev.Timeout, out _); if (!sense) { CSD = mmcBuf; } sense = dev.ReadOcr(out mmcBuf, out _, dev.Timeout, out _); if (!sense) { OCR = mmcBuf; } sense = dev.ReadExtendedCsd(out mmcBuf, out _, dev.Timeout, out _); if (!sense) { ExtendedCSD = mmcBuf; } } break; case DeviceType.SecureDigital: { bool sense = dev.ReadCid(out byte[] sdBuf, out _, dev.Timeout, out _); if (!sense) { CID = sdBuf; } sense = dev.ReadCsd(out sdBuf, out _, dev.Timeout, out _); if (!sense) { CSD = sdBuf; } sense = dev.ReadSdocr(out sdBuf, out _, dev.Timeout, out _); if (!sense) { OCR = sdBuf; } sense = dev.ReadScr(out sdBuf, out _, dev.Timeout, out _); if (!sense) { SCR = sdBuf; } } break; default: DicConsole.ErrorWriteLine("Unknown device type {0}, cannot get information.", dev.Type); break; } }
public static byte[] Encode(Inquiry?inq) { if (inq is null) { return(null); } Inquiry decoded = inq.Value; byte[] buffer = new byte[512]; byte length = 0; buffer[0] = (byte)(decoded.PeripheralQualifier << 5); buffer[0] += decoded.PeripheralDeviceType; if (decoded.RMB) { buffer[1] = 0x80; } buffer[1] += decoded.DeviceTypeModifier; buffer[2] = (byte)(decoded.ISOVersion << 6); buffer[2] += (byte)(decoded.ECMAVersion << 3); buffer[2] += decoded.ANSIVersion; if (decoded.AERC) { buffer[3] = 0x80; } if (decoded.TrmTsk) { buffer[3] += 0x40; } if (decoded.NormACA) { buffer[3] += 0x20; } if (decoded.HiSup) { buffer[3] += 0x10; } buffer[3] += decoded.ResponseDataFormat; if (decoded.AdditionalLength > 0) { length = 5; buffer[4] = decoded.AdditionalLength; } if (decoded.SCCS || decoded.ACC || decoded.TPGS > 0 || decoded.ThreePC || decoded.Reserved2 > 0 || decoded.Protect) { length = 6; if (decoded.SCCS) { buffer[5] = 0x80; } if (decoded.ACC) { buffer[5] += 0x40; } buffer[5] += (byte)(decoded.TPGS << 4); if (decoded.ThreePC) { buffer[5] += 0x08; } buffer[5] += (byte)(decoded.Reserved2 << 1); if (decoded.Protect) { buffer[5] += 0x01; } } if (decoded.BQue || decoded.EncServ || decoded.VS1 || decoded.MultiP || decoded.MChngr || decoded.ACKREQQ || decoded.Addr32 || decoded.Addr16) { length = 7; if (decoded.BQue) { buffer[6] = 0x80; } if (decoded.EncServ) { buffer[6] += 0x40; } if (decoded.VS1) { buffer[6] += 0x20; } if (decoded.MultiP) { buffer[6] += 0x10; } if (decoded.MChngr) { buffer[6] += 0x08; } if (decoded.ACKREQQ) { buffer[6] += 0x04; } if (decoded.Addr32) { buffer[6] += 0x02; } if (decoded.Addr16) { buffer[6] += 0x01; } } if (decoded.RelAddr || decoded.WBus32 || decoded.WBus16 || decoded.Sync || decoded.Linked || decoded.TranDis || decoded.CmdQue || decoded.SftRe) { length = 8; if (decoded.RelAddr) { buffer[7] = 0x80; } if (decoded.WBus32) { buffer[7] += 0x40; } if (decoded.WBus16) { buffer[7] += 0x20; } if (decoded.Sync) { buffer[7] += 0x10; } if (decoded.Linked) { buffer[7] += 0x08; } if (decoded.TranDis) { buffer[7] += 0x04; } if (decoded.CmdQue) { buffer[7] += 0x02; } if (decoded.SftRe) { buffer[7] += 0x01; } } if (decoded.VendorIdentification != null) { length = 16; Array.Copy(decoded.VendorIdentification, 0, buffer, 8, decoded.VendorIdentification.Length >= 8 ? 8 : decoded.VendorIdentification.Length); } if (decoded.ProductIdentification != null) { length = 32; Array.Copy(decoded.ProductIdentification, 0, buffer, 16, decoded.ProductIdentification.Length >= 16 ? 16 : decoded.ProductIdentification.Length); } if (decoded.ProductRevisionLevel != null) { length = 36; Array.Copy(decoded.ProductRevisionLevel, 0, buffer, 32, decoded.ProductRevisionLevel.Length >= 4 ? 4 : decoded.ProductRevisionLevel.Length); } if (decoded.Seagate_DriveSerialNumber != null) { length = 44; Array.Copy(decoded.Seagate_DriveSerialNumber, 0, buffer, 36, 8); } if (decoded.KreonIdentifier != null && decoded.KreonVersion != null) { length = 46; Array.Copy(decoded.KreonIdentifier, 0, buffer, 36, 5); buffer[41] = decoded.KreonSpace; Array.Copy(decoded.KreonVersion, 0, buffer, 42, 5); } if (decoded.HP_WORM || decoded.HP_WORMVersion > 0 || decoded.HP_OBDR != null) { length = 49; if (decoded.HP_WORM) { buffer[40] = 0x01; } buffer[40] += (byte)(decoded.HP_WORMVersion << 1); Array.Copy(decoded.HP_OBDR, 0, buffer, 43, 6); } if (decoded.IsHiMD) { length = 56; Array.Copy(HiMDSignatureContents, 0, buffer, 36, 8); if (decoded.HiMDSpecific != null) { Array.Copy(decoded.HiMDSpecific, 0, buffer, 44, 12); } } if (decoded.VendorSpecific != null && !decoded.IsHiMD) { length = 56; Array.Copy(decoded.VendorSpecific, 0, buffer, 36, 20); } if (decoded.Reserved3 > 0 || decoded.Clocking > 0 || decoded.QAS || decoded.IUS) { length = 57; buffer[56] = (byte)(decoded.Reserved3 << 4); buffer[56] += (byte)(decoded.Clocking << 2); if (decoded.QAS) { buffer[56] += 0x02; } if (decoded.IUS) { buffer[56] += 0x01; } } if (decoded.Reserved4 != 0) { length = 58; buffer[57] = decoded.Reserved4; } if (decoded.VersionDescriptors != null) { length = (byte)(58 + (decoded.VersionDescriptors.Length * 2)); for (int i = 0; i < decoded.VersionDescriptors.Length; i++) { Array.Copy(BitConverter.GetBytes(decoded.VersionDescriptors[i]), 0, buffer, 56 + (i * 2), 2); } } if (decoded.Reserved5 != null) { length = (byte)(74 + decoded.Reserved5.Length); Array.Copy(decoded.Reserved5, 0, buffer, 74, decoded.Reserved5.Length); } if (decoded.VendorSpecific2 != null) { length = (byte)(96 + decoded.VendorSpecific2.Length); Array.Copy(decoded.VendorSpecific2, 0, buffer, 96, decoded.VendorSpecific2.Length); } if (decoded.Seagate_Copyright != null) { length = 144; Array.Copy(decoded.Seagate_Copyright, 0, buffer, 96, 48); } if (decoded.Seagate_ServoPROMPartNo != null) { length = 148; Array.Copy(decoded.Seagate_ServoPROMPartNo, 0, buffer, 144, 4); } buffer[4] = length; byte[] dest = new byte[length]; Array.Copy(buffer, 0, dest, 0, length); return(dest); }
public static Inquiry?Decode(byte[] SCSIInquiryResponse) { if (SCSIInquiryResponse == null) { return(null); } if (SCSIInquiryResponse.Length < 36 && SCSIInquiryResponse.Length != 5) { DicConsole.DebugWriteLine("SCSI INQUIRY decoder", "INQUIRY response is {0} bytes, less than minimum of 36 bytes, decoded data can be incorrect, not decoding.", SCSIInquiryResponse.Length); return(null); } if (SCSIInquiryResponse.Length < SCSIInquiryResponse[4] + 4 && SCSIInquiryResponse.Length != SCSIInquiryResponse[4]) { DicConsole.DebugWriteLine("SCSI INQUIRY decoder", "INQUIRY response length ({0} bytes) is different than specified in length field ({1} bytes), decoded data can be incorrect, not decoding.", SCSIInquiryResponse.Length, SCSIInquiryResponse[4] + 4); return(null); } var decoded = new Inquiry(); if (SCSIInquiryResponse.Length >= 1) { decoded.PeripheralQualifier = (byte)((SCSIInquiryResponse[0] & 0xE0) >> 5); decoded.PeripheralDeviceType = (byte)(SCSIInquiryResponse[0] & 0x1F); } if (SCSIInquiryResponse.Length >= 2) { decoded.RMB = Convert.ToBoolean(SCSIInquiryResponse[1] & 0x80); decoded.DeviceTypeModifier = (byte)(SCSIInquiryResponse[1] & 0x7F); } if (SCSIInquiryResponse.Length >= 3) { decoded.ISOVersion = (byte)((SCSIInquiryResponse[2] & 0xC0) >> 6); decoded.ECMAVersion = (byte)((SCSIInquiryResponse[2] & 0x38) >> 3); decoded.ANSIVersion = (byte)(SCSIInquiryResponse[2] & 0x07); } if (SCSIInquiryResponse.Length >= 4) { decoded.AERC = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x80); decoded.TrmTsk = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x40); decoded.NormACA = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x20); decoded.HiSup = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x10); decoded.ResponseDataFormat = (byte)(SCSIInquiryResponse[3] & 0x07); } if (SCSIInquiryResponse.Length >= 5) { decoded.AdditionalLength = SCSIInquiryResponse[4]; } if (SCSIInquiryResponse.Length >= 6) { decoded.SCCS = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x80); decoded.ACC = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x40); decoded.TPGS = (byte)((SCSIInquiryResponse[5] & 0x30) >> 4); decoded.ThreePC = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x08); decoded.Reserved2 = (byte)((SCSIInquiryResponse[5] & 0x06) >> 1); decoded.Protect = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x01); } if (SCSIInquiryResponse.Length >= 7) { decoded.BQue = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x80); decoded.EncServ = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x40); decoded.VS1 = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x20); decoded.MultiP = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x10); decoded.MChngr = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x08); decoded.ACKREQQ = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x04); decoded.Addr32 = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x02); decoded.Addr16 = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x01); } if (SCSIInquiryResponse.Length >= 8) { decoded.RelAddr = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x80); decoded.WBus32 = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x40); decoded.WBus16 = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x20); decoded.Sync = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x10); decoded.Linked = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x08); decoded.TranDis = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x04); decoded.CmdQue = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x02); decoded.SftRe = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x01); } if (SCSIInquiryResponse.Length >= 16) { decoded.VendorIdentification = new byte[8]; Array.Copy(SCSIInquiryResponse, 8, decoded.VendorIdentification, 0, 8); } if (SCSIInquiryResponse.Length >= 32) { decoded.ProductIdentification = new byte[16]; Array.Copy(SCSIInquiryResponse, 16, decoded.ProductIdentification, 0, 16); } if (SCSIInquiryResponse.Length >= 36) { decoded.ProductRevisionLevel = new byte[4]; Array.Copy(SCSIInquiryResponse, 32, decoded.ProductRevisionLevel, 0, 4); } if (SCSIInquiryResponse.Length >= 44) { // Seagate 1 decoded.SeagatePresent = true; decoded.Seagate_DriveSerialNumber = new byte[8]; Array.Copy(SCSIInquiryResponse, 36, decoded.Seagate_DriveSerialNumber, 0, 8); // Hi-MD decoded.HiMDSignature = new byte[8]; Array.Copy(SCSIInquiryResponse, 36, decoded.HiMDSignature, 0, 8); decoded.IsHiMD = HiMDSignatureContents.SequenceEqual(decoded.HiMDSignature); } if (SCSIInquiryResponse.Length >= 46) { // Kreon decoded.KreonIdentifier = new byte[5]; Array.Copy(SCSIInquiryResponse, 36, decoded.KreonIdentifier, 0, 5); decoded.KreonSpace = SCSIInquiryResponse[41]; decoded.KreonVersion = new byte[5]; Array.Copy(SCSIInquiryResponse, 42, decoded.KreonVersion, 0, 5); if (decoded.KreonSpace == 0x20 && decoded.KreonIdentifier.SequenceEqual(new byte[] { 0x4B, 0x52, 0x45, 0x4F, 0x4E })) { decoded.KreonPresent = true; } } if (SCSIInquiryResponse.Length >= 49) { // HP decoded.HPPresent = true; decoded.HP_WORM |= (SCSIInquiryResponse[40] & 0x01) == 0x01; decoded.HP_WORMVersion = (byte)((SCSIInquiryResponse[40] & 0x7F) >> 1); decoded.HP_OBDR = new byte[6]; Array.Copy(SCSIInquiryResponse, 43, decoded.HP_OBDR, 0, 6); } if (SCSIInquiryResponse.Length >= 56) { if (decoded.IsHiMD) { decoded.HiMDSpecific = new byte[12]; Array.Copy(SCSIInquiryResponse, 44, decoded.HiMDSpecific, 0, 12); } else { decoded.VendorSpecific = new byte[20]; Array.Copy(SCSIInquiryResponse, 36, decoded.VendorSpecific, 0, 20); } // Quantum decoded.QuantumPresent = true; decoded.Qt_ProductFamily = (byte)((SCSIInquiryResponse[36] & 0xF0) >> 4); decoded.Qt_ReleasedFirmware = (byte)(SCSIInquiryResponse[36] & 0x0F); decoded.Qt_FirmwareMajorVersion = SCSIInquiryResponse[37]; decoded.Qt_FirmwareMinorVersion = SCSIInquiryResponse[38]; decoded.Qt_EEPROMFormatMajorVersion = SCSIInquiryResponse[39]; decoded.Qt_EEPROMFormatMinorVersion = SCSIInquiryResponse[40]; decoded.Qt_FirmwarePersonality = SCSIInquiryResponse[41]; decoded.Qt_FirmwareSubPersonality = SCSIInquiryResponse[42]; decoded.Qt_TapeDirectoryFormatVersion = SCSIInquiryResponse[43]; decoded.Qt_ControllerHardwareVersion = SCSIInquiryResponse[44]; decoded.Qt_DriveEEPROMVersion = SCSIInquiryResponse[45]; decoded.Qt_DriveHardwareVersion = SCSIInquiryResponse[46]; decoded.Qt_MediaLoaderFirmwareVersion = SCSIInquiryResponse[47]; decoded.Qt_MediaLoaderHardwareVersion = SCSIInquiryResponse[48]; decoded.Qt_MediaLoaderMechanicalVersion = SCSIInquiryResponse[49]; decoded.Qt_MediaLoaderPresent = SCSIInquiryResponse[50] > 0; decoded.Qt_LibraryPresent = SCSIInquiryResponse[51] > 0; decoded.Qt_ModuleRevision = new byte[4]; Array.Copy(SCSIInquiryResponse, 52, decoded.Qt_ModuleRevision, 0, 4); // IBM decoded.IBMPresent = true; decoded.IBM_AutDis |= (SCSIInquiryResponse[36] & 0x01) == 0x01; decoded.IBM_PerformanceLimit = SCSIInquiryResponse[37]; decoded.IBM_OEMSpecific = SCSIInquiryResponse[41]; } if (SCSIInquiryResponse.Length >= 57) { decoded.Reserved3 = (byte)((SCSIInquiryResponse[56] & 0xF0) >> 4); decoded.Clocking = (byte)((SCSIInquiryResponse[56] & 0x0C) >> 2); decoded.QAS = Convert.ToBoolean(SCSIInquiryResponse[56] & 0x02); decoded.IUS = Convert.ToBoolean(SCSIInquiryResponse[56] & 0x01); } if (SCSIInquiryResponse.Length >= 58) { decoded.Reserved4 = SCSIInquiryResponse[57]; } if (SCSIInquiryResponse.Length >= 60) { int descriptorsNo; if (SCSIInquiryResponse.Length >= 74) { descriptorsNo = 8; } else { descriptorsNo = (SCSIInquiryResponse.Length - 58) / 2; } decoded.VersionDescriptors = new ushort[descriptorsNo]; for (int i = 0; i < descriptorsNo; i++) { decoded.VersionDescriptors[i] = BitConverter.ToUInt16(SCSIInquiryResponse, 58 + (i * 2)); } } if (SCSIInquiryResponse.Length >= 75 && SCSIInquiryResponse.Length < 96) { decoded.Reserved5 = new byte[SCSIInquiryResponse.Length - 74]; Array.Copy(SCSIInquiryResponse, 74, decoded.Reserved5, 0, SCSIInquiryResponse.Length - 74); } if (SCSIInquiryResponse.Length >= 96) { decoded.Reserved5 = new byte[22]; Array.Copy(SCSIInquiryResponse, 74, decoded.Reserved5, 0, 22); } if (SCSIInquiryResponse.Length > 96) { decoded.VendorSpecific2 = new byte[SCSIInquiryResponse.Length - 96]; Array.Copy(SCSIInquiryResponse, 96, decoded.VendorSpecific2, 0, SCSIInquiryResponse.Length - 96); } if (SCSIInquiryResponse.Length >= 144) { // Seagate 2 decoded.Seagate2Present = true; decoded.Seagate_Copyright = new byte[48]; Array.Copy(SCSIInquiryResponse, 96, decoded.Seagate_Copyright, 0, 48); } if (SCSIInquiryResponse.Length < 148) { return(decoded); } // Seagate 2 decoded.Seagate3Present = true; decoded.Seagate_ServoPROMPartNo = new byte[4]; Array.Copy(SCSIInquiryResponse, 144, decoded.Seagate_ServoPROMPartNo, 0, 4); return(decoded); }