123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- /* 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 System;
- using System.Collections.Generic;
- using System.Text;
- using Utilities;
- namespace SCSI
- {
- public class StandardInquiryData
- {
- public byte PeripheralQualifier;
- public byte PeripheralDeviceType;
- public bool RMB; // Removable media bit
- public byte Version; // We only support Version == 2
- public bool NormACA; // Normal ACA Supported
- public bool HiSup; // Hierarchical Support
- public byte ResponseDataFormat;
- public byte AdditionalLength; // Number of bytes following this byte
- public bool SCCS; // SCC Supported
- public bool ACC; // Access Controls Coordinator
- public byte TPGS; // Target Port Group Support
- public bool ThirdPartyCopy; // 3PC
- public bool Protect;
- public bool EncServ; // Enclosure Services
- public bool VS1; // Vendor specific
- public bool MultiP; // Multi Port
- public bool MChngr; // Medium Changer
- public bool Addr16; // Indicates that the SCSI target device supports 16-bit wide SCSI addresses
- public bool WBus16; // Indicates that the SCSI target device supports 16-bit wide data transfers
- public bool Sync; // Indicates that the SCSI target device supports synchronous data transfer
- public bool CmdQue; // Command Queuing
- public bool VS2; // Vendor specific
- /// <summary>
- /// 8 characters
- /// </summary>
- public string VendorIdentification;
- /// <summary>
- /// 16 characters
- /// </summary>
- public string ProductIdentification;
- /// <summary>
- /// 4 characters
- /// </summary>
- public string ProductRevisionLevel;
- public ulong DriveSerialNumber;
- // Vendor Unique
- public byte Clocking;
- public bool QAS;
- public bool IUS;
- public List<VersionDescriptorName> VersionDescriptors = new List<VersionDescriptorName>(); // 8 descriptors (16 bytes)
- public StandardInquiryData()
- {
- ResponseDataFormat = 2;
- AdditionalLength = 91;
- }
- public StandardInquiryData(byte[] buffer, int offset)
- {
- PeripheralQualifier = (byte)(buffer[offset + 0] >> 5);
- PeripheralDeviceType = (byte)(buffer[offset + 0] & 0x1F);
- RMB = (buffer[offset + 1] & 0x80) != 0;
- Version = buffer[offset + 2];
- if (Version != 2)
- {
- return;
- }
- NormACA = (buffer[offset + 3] & 0x20) != 0;
- HiSup = (buffer[offset + 3] & 0x10) != 0;
- ResponseDataFormat = (byte)(buffer[offset + 3] & 0x0F);
- AdditionalLength = buffer[offset + 4];
- if (AdditionalLength < 91) // Standard Inquiry data should be at least 96 bytes (so the AdditionalLength must be at least 96 - 5)
- {
- return;
- }
- SCCS = (buffer[offset + 5] & 0x80) != 0;
- ACC = (buffer[offset + 5] & 0x40) != 0;
- TPGS = (byte)((buffer[offset + 5] >> 4) & 0x03);
- ThirdPartyCopy = (buffer[offset + 5] & 0x08) != 0;
- Protect = (buffer[offset + 5] & 0x01) != 0;
- EncServ = (buffer[offset + 6] & 0x40) != 0;
- VS1 = (buffer[offset + 6] & 0x20) != 0;
- MultiP = (buffer[offset + 6] & 0x10) != 0;
- MChngr = (buffer[offset + 6] & 0x08) != 0;
- Addr16 = (buffer[offset + 6] & 0x01) != 0;
- WBus16 = (buffer[offset + 7] & 0x20) != 0;
- Sync = (buffer[offset + 7] & 0x10) != 0;
- CmdQue = (buffer[offset + 7] & 0x02) != 0;
- VS2 = (buffer[offset + 7] & 0x01) != 0;
- VendorIdentification = Encoding.ASCII.GetString(buffer, 8, 8);
- ProductIdentification = Encoding.ASCII.GetString(buffer, 16, 16);
- ProductRevisionLevel = Encoding.ASCII.GetString(buffer, 32, 4);
- DriveSerialNumber = BigEndianConverter.ToUInt64(buffer, 36);
- Clocking = (byte)((buffer[offset + 56] >> 2) & 0x03);
- QAS = (buffer[offset + 56] & 0x02) != 0;
- IUS = (buffer[offset + 56] & 0x01) != 0;
- for (int index = 0; index < 8; index++)
- {
- VersionDescriptorName versionDescriptor = (VersionDescriptorName)BigEndianConverter.ToUInt16(buffer, offset + 58 + index * 2);
- VersionDescriptors.Add(versionDescriptor);
- }
- }
- public byte[] GetBytes()
- {
- byte[] buffer = new byte[96];
- buffer[0] |= (byte)(PeripheralQualifier << 5);
- buffer[0] |= (byte)(PeripheralQualifier & 0x1F);
- if (RMB)
- {
- buffer[1] |= 0x80;
- }
- buffer[2] = Version;
- if (NormACA)
- {
- buffer[3] |= 0x20;
- }
- if (HiSup)
- {
- buffer[3] |= 0x10;
- }
- buffer[3] |= (byte)(ResponseDataFormat & 0x0F);
- buffer[4] = AdditionalLength;
- if (SCCS)
- {
- buffer[5] |= 0x80;
- }
- if (ACC)
- {
- buffer[5] |= 0x40;
- }
- buffer[5] |= (byte)((TPGS & 0x03) << 4);
- if (ThirdPartyCopy)
- {
- buffer[5] |= 0x08;
- }
- if (Protect)
- {
- buffer[5] |= 0x01;
- }
- if (EncServ)
- {
- buffer[6] |= 0x40;
- }
- if (VS1)
- {
- buffer[6] |= 0x20;
- }
- if (MultiP)
- {
- buffer[6] |= 0x10;
- }
- if (MChngr)
- {
- buffer[6] |= 0x08;
- }
- if (Addr16)
- {
- buffer[6] |= 0x01;
- }
- if (WBus16)
- {
- buffer[7] |= 0x20;
- }
- if (Sync)
- {
- buffer[7] |= 0x10;
- }
- if (CmdQue)
- {
- buffer[7] |= 0x02;
- }
- if (VS2)
- {
- buffer[7] |= 0x01;
- }
- Array.Copy(ASCIIEncoding.ASCII.GetBytes(VendorIdentification), 0, buffer, 8, Math.Min(VendorIdentification.Length, 8));
- Array.Copy(ASCIIEncoding.ASCII.GetBytes(ProductIdentification), 0, buffer, 16, Math.Min(ProductIdentification.Length, 16));
- Array.Copy(ASCIIEncoding.ASCII.GetBytes(ProductRevisionLevel), 0, buffer, 32, 4);
- Array.Copy(BigEndianConverter.GetBytes(DriveSerialNumber), 0, buffer, 36, 8);
- buffer[56] |= (byte)((Clocking & 0x03) << 2);
- if (QAS)
- {
- buffer[56] |= 0x02;
- }
- if (IUS)
- {
- buffer[56] |= 0x01;
- }
- for (int index = 0; index < 8; index++)
- {
- ushort versionDescriptor = 0;
- if (index < VersionDescriptors.Count)
- {
- versionDescriptor = (ushort)VersionDescriptors[index];
- }
- BigEndianWriter.WriteUInt16(buffer, 58 + index * 2, versionDescriptor);
- }
- return buffer;
- }
- }
- }
|