public UnitSerialNumberVPDPage(byte[] buffer, int offset)
 {
     PeripheralQualifier  = (byte)(buffer[offset + 0] >> 5);
     PeripheralDeviceType = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F);
     PageCode             = (VitalProductDataPageName)buffer[offset + 1];
     PageLength           = buffer[offset + 3];
     ProductSerialNumber  = ASCIIEncoding.ASCII.GetString(buffer, offset + 4, PageLength);
 }
 public BlockDeviceCharacteristicsVPDPage(byte[] buffer, int offset)
 {
     PeripheralQualifier  = (byte)(buffer[offset + 0] >> 5);
     PeripheralDeviceType = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F);
     PageCode             = (VitalProductDataPageName)buffer[offset + 1];
     PageLength           = buffer[offset + 3];
     MediumRotationRate   = BigEndianConverter.ToUInt16(buffer, offset + 4);
     Reserved             = BigEndianConverter.ToUInt16(buffer, offset + 6);
 }
Example #3
0
        private SCSIStatusCodeName ReportLUNs(out byte[] response)
        {
            uint               bytesReturned;
            uint               outBufferLength = 4096;
            IntPtr             outBuffer       = Marshal.AllocHGlobal((int)outBufferLength);
            SCSIStatusCodeName status;

            if (!DeviceIoControl(m_handle, IOCTL_SCSI_GET_INQUIRY_DATA, IntPtr.Zero, 0, outBuffer, outBufferLength, out bytesReturned, IntPtr.Zero))
            {
                Win32Error lastError = (Win32Error)Marshal.GetLastWin32Error();
                Log(Severity.Error, "DeviceIoControl/IOCTL_SCSI_GET_INQUIRY_DATA error: {0}, Device path: {1}", lastError, m_path);
                response = VirtualSCSITarget.FormatSenseData(SenseDataParameter.GetIllegalRequestUnsupportedCommandCodeSenseData());
                status   = SCSIStatusCodeName.CheckCondition;
            }
            else
            {
                List <SCSI_INQUIRY_DATA> devices   = SCSI_ADAPTER_BUS_INFO.GetInquiryDataForAllDevices(outBuffer);
                ReportLUNsParameter      parameter = new ReportLUNsParameter();
                foreach (SCSI_INQUIRY_DATA device in devices)
                {
                    // If the device has been claimed by a class driver then passthrough IOCTLs must go through the class driver
                    if (!device.DeviceClaimed)
                    {
                        PeripheralDeviceType deviceType = (PeripheralDeviceType)(device.InquiryData[0] & 0x1F);
                        if (deviceType == PeripheralDeviceType.DirectAccessBlockDevice |
                            deviceType == PeripheralDeviceType.SequentialAccessDevice |
                            deviceType == PeripheralDeviceType.CDRomDevice)
                        {
                            byte?associatedLUN = m_logicalUnitManager.FindAssociatedLUN(device.PathId, device.TargetId, device.Lun);
                            if (!associatedLUN.HasValue)
                            {
                                associatedLUN = m_logicalUnitManager.FindUnusedLUN();
                                LogicalUnit logicalUnit = new LogicalUnit();
                                logicalUnit.AssociatedLun = associatedLUN.Value;
                                logicalUnit.PathId        = device.PathId;
                                logicalUnit.TargetId      = device.TargetId;
                                logicalUnit.TargetLun     = device.Lun;
                                logicalUnit.DeviceType    = deviceType;
                                m_logicalUnitManager.AddLogicalUnit(logicalUnit);
                                Log(Severity.Verbose, "Assigned virtual LUN {0} to device PathId: {1}, TargetId: {2}, LUN: {3}", associatedLUN.Value, device.PathId, device.TargetId, device.Lun);
                            }

                            if (!associatedLUN.HasValue)
                            {
                                throw new NotImplementedException("The maximum number of LUNs supported has been reached");
                            }
                            parameter.LUNList.Add(associatedLUN.Value);
                        }
                    }
                }
                response = parameter.GetBytes();
                Log(Severity.Verbose, "DeviceIoControl/IOCTL_SCSI_GET_INQUIRY_DATA reported {0} usable devices", parameter.LUNList.Count);
                status = SCSIStatusCodeName.Good;
            }
            Marshal.FreeHGlobal(outBuffer);
            return(status);
        }
 public SupportedVitaLProductDataPages(byte[] buffer, int offset)
 {
     PeripheralQualifier  = (byte)(buffer[offset + 0] >> 5);
     PeripheralDeviceType = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F);
     PageLength           = buffer[offset + 3];
     for (int index = 0; index < PageLength; index++)
     {
         SupportedPageList.Add(buffer[offset + 4 + index]);
     }
 }
Example #5
0
 public BlockLimitsVPDPage(byte[] buffer, int offset)
 {
     PeripheralQualifier              = (byte)(buffer[offset + 0] >> 5);
     PeripheralDeviceType             = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F);
     PageCode                         = (VitalProductDataPageName)buffer[offset + 1];
     PageLength                       = buffer[offset + 3];
     OptimalTransferLengthGranularity = BigEndianConverter.ToUInt16(buffer, offset + 6);
     MaximumTransferLength            = BigEndianConverter.ToUInt32(buffer, offset + 8);
     OptimalTransferLength            = BigEndianConverter.ToUInt32(buffer, offset + 12);
 }
Example #6
0
        public static string strDeviceType(PeripheralDeviceType devtype)
        {
            switch (devtype)
            {
            case PeripheralDeviceType.BLOCK:
                return("Block Device");

            case PeripheralDeviceType.CDROM:
                return("CD/DVD-ROM");

            default:
                return("Unknown SCSI Device.");
            }
        }
Example #7
0
        public StandardInquiryData(byte[] buffer, int offset)
        {
            PeripheralQualifier  = (byte)(buffer[offset + 0] >> 5);
            PeripheralDeviceType = (PeripheralDeviceType)(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 static uint GetDeviceReadTransferLength(byte[] commandBytes, PeripheralDeviceType deviceType, uint blockSize)
        {
            if (deviceType == PeripheralDeviceType.DirectAccessBlockDevice ||
                deviceType == PeripheralDeviceType.CDRomDevice)
            {
                return(GetBlockDeviceReadTransferLength(commandBytes, blockSize));
            }
            else if (deviceType == PeripheralDeviceType.SequentialAccessDevice)
            {
                return(SCSICommandParser.GetSequentialAccessDeviceReadTransferLength(commandBytes, blockSize));
            }

            throw new NotSupportedException("Device Type Not Supported!");
        }
        public DeviceIdentificationVPDPage(byte[] buffer, int offset)
        {
            PeripheralQualifier  = (byte)(buffer[offset + 0] >> 5);
            PeripheralDeviceType = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F);
            PageCode             = (VitalProductDataPageName)buffer[offset + 1];
            PageLength           = BigEndianConverter.ToUInt16(buffer, 2);
            int parameterOffset = 4;

            while (parameterOffset < PageLength)
            {
                IdentificationDescriptor descriptor = new IdentificationDescriptor(buffer, offset + parameterOffset);
                IdentificationDescriptorList.Add(descriptor);
                parameterOffset += descriptor.Length;
            }
        }
Example #10
0
        // Parse CDB allocation length (bytes) based on SPC-3, SSC-3, and SBC-3
        public static uint GetCDBTransferLength(byte[] commandBytes, PeripheralDeviceType deviceType)
        {
            switch ((SCSIOpCodeName)commandBytes[0])
            {
            case SCSIOpCodeName.RecoverBufferedData:               // DATA_IN (2-4)
                return(BigEndianReader.ReadUInt24(commandBytes, 2));

            case SCSIOpCodeName.ReadBlockLimits:                   // DATA_IN (6 bytes)
                return(6);

            case SCSIOpCodeName.ReadCapacity10:                    // DATA_IN (8 bytes)
                return(8);

            case SCSIOpCodeName.ReadPosition:                      // DATA_IN (7-8)
                if (deviceType == PeripheralDeviceType.SequentialAccessDevice)
                {
                    if (commandBytes[1] == 0x00 || commandBytes[1] == 0x01)
                    {
                        return(20);
                    }
                    else if (commandBytes[1] == 0x06)
                    {
                        return(32);
                    }
                    else
                    {
                        return(BigEndianConverter.ToUInt16(commandBytes, 7));
                    }
                }
                else
                {
                    return(BigEndianConverter.ToUInt16(commandBytes, 7));
                }

            case SCSIOpCodeName.ReportDensitySupport:              // DATA_IN (7-8)
            case SCSIOpCodeName.LogSelect10:                       // DATA_IN (7-8)
            case SCSIOpCodeName.LogSense10:                        // DATA_IN (7-8)
            case SCSIOpCodeName.ModeSelect10:                      // DATA_IN (7-8)
            case SCSIOpCodeName.ModeSense10:                       // DATA_IN (7-8)
            case SCSIOpCodeName.PersistentReserveIn:               // DATA_IN (7-8)
            case SCSIOpCodeName.ReadLong10:                        // DATA_IN (7-8)
            case SCSIOpCodeName.ReadDefectData10:                  // DATA_IN (7-8)
                return(BigEndianConverter.ToUInt16(commandBytes, 7));

            case SCSIOpCodeName.ModeSelect6:                       // DATA_IN (4)
            case SCSIOpCodeName.ModeSense6:                        // DATA_IN (4)
            case SCSIOpCodeName.RequestSense:                      // DATA_IN (4)
                return((uint)commandBytes[4]);

            case SCSIOpCodeName.ReadAttribute16:                   // DATA_IN (10-13)
            case SCSIOpCodeName.ThirdPartyCopyIn:                  // DATA_IN (10-13) ?
                return(BigEndianConverter.ToUInt32(commandBytes, 10));

            case SCSIOpCodeName.ReadBuffer10:                      // DATA_IN (6-8)
                return(BigEndianReader.ReadUInt24(commandBytes, 6));

            case SCSIOpCodeName.ReceiveDiagnosticResults:          // DATA_IN (3-4)
            case SCSIOpCodeName.Inquiry:                           // DATA_IN (3-4)
                return(BigEndianConverter.ToUInt16(commandBytes, 3));

            case SCSIOpCodeName.ReportLUNs:                        // DATA_IN (6-9)
            case SCSIOpCodeName.SecurityProtocolIn:                // DATA_IN (6-9)
            case SCSIOpCodeName.ReadDefectData12:                  // DATA_IN (6-9)
                return(BigEndianConverter.ToUInt32(commandBytes, 6));

            case SCSIOpCodeName.ServiceActionIn16:
                if (commandBytes[1] == (byte)ServiceAction.ReadLong16)         // DATA_IN (12-13)
                {
                    return(BigEndianConverter.ToUInt16(commandBytes, 12));
                }
                if (commandBytes[1] == (byte)ServiceAction.ReadCapacity16)     // DATA_IN (10-13)
                {
                    return(BigEndianConverter.ToUInt32(commandBytes, 10));
                }
                return(512);

            default:
                // XXX: Need to complete SBC-3 (ex: XDREAD)
                return(512);
            }
        }