/// <summary> /// /// </summary> /// <returns></returns> public CommandStatus ReadDiskInformation(out DiskInformation result) { if (m_logger != null) { string args = "out result"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadDiskInformation(" + args + ")")); } ushort len = 0; result = null; using (Command cmd = new Command(ScsiCommandCode.ReadDiskInformation, 10, 34, Command.CmdDirection.In, 60)) { cmd.SetCDB16(7, 34); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer16(0); if (len <= 34) { result = new DiskInformation(cmd.GetBuffer(), cmd.BufferSize); return CommandStatus.Success; } len += 2; } using (Command cmd = new Command(ScsiCommandCode.ReadDiskInformation, 10, len, Command.CmdDirection.In, 60)) { cmd.SetCDB16(7, len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; result = new DiskInformation(cmd.GetBuffer(), cmd.BufferSize); } return CommandStatus.Success; }
/// <summary> /// This method reads the PAC data for a blu-ray disk /// </summary> /// <param name="pacid">the pac id of the pac to read</param> /// <param name="pacfmt">the format of the pac to read</param> /// <param name="data">return storage for the pac data</param> /// <returns></returns> public CommandStatus ReadDiskStructurePac(uint pacid, byte pacfmt, out byte [] data) { data = null; if (m_logger != null) { string args = "out byte[] data"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadDvdStructurePac(" + args + ")")); } ushort len = 4; using (Command cmd = new Command(ScsiCommandCode.ReadDvdStructure, 12, len, Command.CmdDirection.In, 60)) { cmd.SetCDB24(2, pacid); cmd.SetCDB8(6, pacfmt); cmd.SetCDB8(7, 0x30); // Read PAC data cmd.SetCDB16(8, len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = (ushort)(cmd.GetBuffer16(0) + 2); if (len == 2) { data = new byte[0]; return CommandStatus.Success; } Debug.Assert(len < 8192); } using (Command cmd = new Command(ScsiCommandCode.ReadDvdStructure, 12, len, Command.CmdDirection.In, 60)) { cmd.SetCDB24(2, pacid); cmd.SetCDB8(6, pacfmt); cmd.SetCDB8(7, 0x30); // Read manufacturing information cmd.SetCDB16(8, len); // Up to 2k of data CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = (ushort)(cmd.GetBuffer16(0) + 2); data = new byte[len]; Marshal.Copy(cmd.GetBuffer(), data, 0, len); } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <returns></returns> public CommandStatus SendCueSheet(byte [] sheet) { if (m_logger != null) { string args = sheet.ToString(); m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.SendCueSheet(" + args + ")")); m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 1, "Cue Sheet")); m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 1, "----------------------------------------------")); for (int i = 0; i < sheet.GetLength(0) / 8; i++) { string s = "" ; for (int j = 0; j < 8; j++) { if (j != 0) s += " "; s += sheet[i * 8 + j].ToString("x2"); } m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 1, s)); } m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 1, "----------------------------------------------")); } ushort len = (ushort)sheet.GetLength(0); using (Command cmd = new Command(ScsiCommandCode.SendCueSheet, 10, len, Command.CmdDirection.Out, 10)) { cmd.SetCDB32(5, len); cmd.SetCDB8(5, 0); Marshal.Copy(sheet, 0, cmd.GetBuffer(), len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <param name="type"></param> /// <param name="start"></param> /// <param name="result"></param> /// <returns></returns> public CommandStatus GetConfiguration(GetConfigType type, ushort start, out FeatureList result) { if (m_logger != null) { string args = type.ToString() + ", " + start.ToString() + ", out result"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.GetConfiguration(" + args + ")")); } uint len = 0; result = null; if (type == GetConfigType.Reserved) throw new Exception("cannot use reserved value") ; using (Command cmd = new Command(ScsiCommandCode.GetConfiguration, 10, 8, Command.CmdDirection.In, 10)) { cmd.SetCDB8(1, (byte)type); cmd.SetCDB16(2, start); cmd.SetCDB16(7, 8); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer32(0); len += 4; // Add four for the length field } using (Command cmd = new Command(ScsiCommandCode.GetConfiguration, 10, (ushort)len, Command.CmdDirection.In, 10)) { cmd.SetCDB8(1, (byte)type); cmd.SetCDB16(2, start); cmd.SetCDB16(7, (ushort)len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; result = new FeatureList(cmd.GetBuffer(), cmd.BufferSize); } return CommandStatus.Success; }
/// <summary> /// This method reads the ATIP information from a CD media /// </summary> /// <returns></returns> public CommandStatus ReadAtip(out AtipInfo info) { ushort len; info = null; if (m_logger != null) { string args = "info"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadAtip(" + args + ")")); } using (Command cmd = new Command(ScsiCommandCode.ReadTocPmaAtip, 10, 32, Command.CmdDirection.In, 5 * 60)) { cmd.SetCDB8(2, 4); cmd.SetCDB16(7, 32); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer16(0); len += 2; } if (len <= 4) return CommandStatus.Success; using (Command cmd = new Command(ScsiCommandCode.ReadTocPmaAtip, 10, len, Command.CmdDirection.In, 5 * 60)) { cmd.SetCDB8(2, 4); cmd.SetCDB16(7, len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; info = new AtipInfo(cmd.GetBuffer(), len); } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <returns></returns> public CommandStatus ReadTrackInformation(ReadTrackType type, uint addr, out TrackInformation info) { info = null; if (m_logger != null) { string args = "info"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadTrackInformation(" + args + ")")); } using (Command cmd = new Command(ScsiCommandCode.ReadTrackInformation, 10, 48, Command.CmdDirection.In, 5 * 60)) { cmd.SetCDB8(1, (byte)type); cmd.SetCDB32(2, addr); cmd.SetCDB16(7, 40); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; info = new TrackInformation(cmd.GetBuffer(), cmd.BufferSize); } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <param name="pc"></param> /// <param name="page"></param> /// <param name="table"></param> /// <returns></returns> public CommandStatus ModeSense(PageControl pc, byte page, out ModeTable table) { if (m_logger != null) { string args = pc.ToString() + ", " + page.ToString() + ", out result"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ModeSense(" + args + ")")); } ushort len = 0; table = null; byte b = 0; b |= (byte)((byte)(pc) << 7); b |= (byte)(page & 0x3f); using (Command cmd = new Command(ScsiCommandCode.ModeSense, 10, 8, Command.CmdDirection.In, 60 * 5)) { cmd.SetCDB8(1, 8); // Disable block descriptors cmd.SetCDB8(2, b); cmd.SetCDB16(7, 8); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer16(0); len += 2; } using (Command cmd = new Command(ScsiCommandCode.ModeSense, 10, len, Command.CmdDirection.In, 60 * 5)) { cmd.SetCDB8(1, 8); // Disable block descriptors cmd.SetCDB8(2, b); cmd.SetCDB16(7, len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; table = new ModeTable(cmd.GetBuffer(), cmd.BufferSize); } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <returns></returns> public CommandStatus ReadFormatCapacities(bool all, out IList<CapacityDescriptor> caplist) { caplist = new List<CapacityDescriptor>(); if (m_logger != null) { string args = all.ToString() + ", out caplist"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadFormatCapacities(" + args + ")")); } int len; using (Command cmd = new Command(ScsiCommandCode.ReadFormatCapacities, 10, 8, Command.CmdDirection.In, 60)) { cmd.SetCDB16(7, 8); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer8(3) + 4; } using (Command cmd = new Command(ScsiCommandCode.ReadFormatCapacities, 10, len, Command.CmdDirection.In, 60)) { cmd.SetCDB16(7, (ushort)len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; int offset = 4; len = cmd.GetBuffer8(3) + 4; while (offset < len) { caplist.Add(new CapacityDescriptor(cmd.GetBuffer(), offset, cmd.BufferSize)); offset += 8; } } return CommandStatus.Success; }
/// <summary> /// Perform a SCSI inquiry on the device to get information about the device /// </summary> /// <param name="result">The return value describing the inquiry results</param> /// <returns></returns> public CommandStatus Inquiry(out InquiryResult result) { if (m_logger != null) { string args = "out result"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.Inquiry(" + args + ")")); } result = null; byte len = 0; using (Command cmd = new Command(ScsiCommandCode.Inquiry, 6, 36, Command.CmdDirection.In, 10)) { cmd.SetCDB16(3, 36); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer8(4); len += 5; if (len <= cmd.BufferSize) { result = new InquiryResult(cmd.GetBuffer(), len); if (m_logger != null) m_logger.DumpBuffer(9, "Raw Inquiry Result", cmd.GetBuffer(), len); return CommandStatus.Success; } // // As an oddity, the Sony DW-G120A only supports requests that are an even number // of bytes. // if ((len % 2) == 1) len = (byte)((len / 2 * 2) + (((len % 2) == 1) ? 2 : 0)); } using (Command cmd = new Command(ScsiCommandCode.Inquiry, 6, len, Command.CmdDirection.In, 100)) { cmd.SetCDB8(4, len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; result = new InquiryResult(cmd.GetBuffer(), cmd.BufferSize); if (m_logger != null) m_logger.DumpBuffer(9, "Raw Inquiry Result", cmd.GetBuffer(), cmd.BufferSize); } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <param name="save"></param> /// <param name="table"></param> /// <returns></returns> public CommandStatus ModeSelect(bool save, ModeTable table) { if (m_logger != null) { string t = ""; for (int i = 0; i < table.Pages.Count; i++) { if (t.Length > 0) t += ", "; t = t + table.Pages[i].PageCode; } string args = save.ToString() + ", ModeTable(" + t + ")"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ModeSelect(" + args + ")")); } using (Command cmd = new Command(ScsiCommandCode.ModeSelect, 10, table.Size, Command.CmdDirection.Out, 60 * 5)) { byte b = 0x10; if (save) b |= 0x01; cmd.SetCDB8(1, b); cmd.SetCDB16(7, table.Size); table.Format(cmd.GetBuffer()); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <returns></returns> public CommandStatus GetPerformance(uint lba, PerformanceList.DataType rwtype, PerformanceList.ExceptType extype, out PerformanceList list) { list = null; if (m_logger != null) { string args = rwtype.ToString() + ", " + extype.ToString() + ", list"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.GetPerformance(" + args + ")")); } uint len = 0; using (Command cmd = new Command(ScsiCommandCode.GetPerformance, 12, 24, Command.CmdDirection.In, 10)) { byte b = 0x10; if (rwtype == PerformanceList.DataType.WriteData) b |= 0x04 ; b |= (byte)extype; cmd.SetCDB8(1, b); cmd.SetCDB16(8, 1); if (extype == PerformanceList.ExceptType.Entire) cmd.SetCDB32(2, lba); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer32(0); len += 4; // For the length field } using (Command cmd = new Command(ScsiCommandCode.GetPerformance, 12, (ushort)len, Command.CmdDirection.In, 10)) { byte b = 0x10; if (rwtype == PerformanceList.DataType.WriteData) b |= 0x04; b |= (byte)extype; cmd.SetCDB8(1, b); if (extype == PerformanceList.ExceptType.Entire) cmd.SetCDB32(2, lba); cmd.SetCDB16(8, (ushort)((len - 8) / 16)); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; list = new PerformanceList(cmd.GetBuffer(), cmd.BufferSize); } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <returns></returns> public CommandStatus GetSpeed(out SpeedDescriptorList list) { ushort initial_size = 8 + 4 * 16; list = null; if (m_logger != null) { string args = string.Empty; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.GetWriteSpeed(" + args + ")")); } uint len = 0; using (Command cmd = new Command(ScsiCommandCode.GetPerformance, 12, initial_size, Command.CmdDirection.In, 10 * 60)) { cmd.SetCDB16(8, (ushort)((initial_size - 8) / 16)); cmd.SetCDB8(10, 3); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer32(0); len += 4; // For the length field } using (Command cmd = new Command(ScsiCommandCode.GetPerformance, 12, (ushort)len, Command.CmdDirection.In, 10 * 60)) { cmd.SetCDB16(8, (ushort)((len - 8) / 16)); cmd.SetCDB8(10, 3); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; list = new SpeedDescriptorList(cmd.GetBuffer(), cmd.BufferSize); } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <param name="polled"></param> /// <param name="request"></param> /// <param name="result"></param> /// <returns></returns> public CommandStatus GetEventStatusNotification(bool polled, NotificationClass request, out EventStatusNotification result) { if (m_logger != null) { string args = polled.ToString() + ", " + request.ToString() + ", out result"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.GetEventStatusNotification(" + args + ")")); } ushort len = 0; result = null; using (Command cmd = new Command(ScsiCommandCode.GetEventStatusNotification, 10, 4, Command.CmdDirection.In, 10)) { if (polled) cmd.SetCDB8(1, 1); cmd.SetCDB8(4, (byte)request); cmd.SetCDB16(7, 4); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; byte n = cmd.GetBuffer8(2); if ((n & 0x80) != 0) { // There are no events, just capture the header result = new EventStatusNotification(cmd.GetBuffer(), cmd.BufferSize); return CommandStatus.Success; } // // There are event notifications to be grabbed, allocate space for these // len = cmd.GetBuffer16(0); len += 4; // For the length field } using (Command cmd = new Command(ScsiCommandCode.GetEventStatusNotification, 10, len, Command.CmdDirection.In, 10)) { if (polled) cmd.SetCDB8(1, 1); cmd.SetCDB8(4, (byte)request); cmd.SetCDB16(7, len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; result = new EventStatusNotification(cmd.GetBuffer(), cmd.BufferSize); } return CommandStatus.Success; }
/// <summary> /// Return the data from a ReadDvdStructure request as a series of bytes. /// </summary> /// <param name="format">the format of the read dvd structure request</param> /// <param name="data">the AACS volume identifier</param> /// <returns>status of command execution</returns> private CommandStatus ReadDiskStructureReturnBytes(byte format, out byte[] data) { data = null; if (m_logger != null) { string args = "out byte[] data"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadDvdStructureAACSVolumeIdentifier(" + args + ")")); } ushort len = 4; using (Command cmd = new Command(ScsiCommandCode.ReadDvdStructure, 12, len, Command.CmdDirection.In, 60)) { cmd.SetCDB8(7, format); // Read manufacturing information cmd.SetCDB16(8, len); // Up to 2k of data CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer16(0); if (len == 0) { data = new byte[0]; return CommandStatus.Success; } Debug.Assert(len < 8192); } using (Command cmd = new Command(ScsiCommandCode.ReadDvdStructure, 12, len, Command.CmdDirection.In, 60)) { cmd.SetCDB8(7, format); // Read manufacturing information cmd.SetCDB16(8, len); // Up to 2k of data CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer16(0); data = new byte[len]; Marshal.Copy(cmd.GetBuffer(), data, 0, len); } return CommandStatus.Success; }
/// <summary> /// This method requests that the SCSI device transfer data to the given buffer /// </summary> /// <param name="force">If true, the data is forced from the media and cannot be read from the cache</param> /// <param name="streaming">If true, this is a streaming read</param> /// <param name="lba">The starting logical address for the data</param> /// <param name="length">The length of the data to read</param> /// <param name="data">The data buffer to received the data</param> /// <returns></returns> public CommandStatus Read(bool force, bool streaming, uint lba, uint length, ref byte [] data) { if (m_logger != null) { string args = force.ToString() + ", " + streaming.ToString() + ", " + lba.ToString() + ", " + length.ToString() + ", buffer"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.Read(" + args + ")")); } if (streaming || length > 65535) { using (Command cmd = new Command(ScsiCommandCode.Read12, 12, (ushort)data.GetLength(0), Command.CmdDirection.In, 5 * 60)) { if (force) cmd.SetCDB8(1, 4); // Set the FUA bit cmd.SetCDB32(2, lba); cmd.SetCDB32(6, length); if (streaming) cmd.SetCDB8(10, 0x80); // Set the streaming bit CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; Marshal.Copy(cmd.GetBuffer(), data, 0, data.GetLength(0)); } } else { using (Command cmd = new Command(ScsiCommandCode.Read, 10, (ushort)data.GetLength(0), Command.CmdDirection.In, 5 * 60)) { if (force) cmd.SetCDB8(1, 4); // Set the FUA bit cmd.SetCDB32(2, lba); cmd.SetCDB16(7, (ushort)length); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; Marshal.Copy(cmd.GetBuffer(), data, 0, data.GetLength(0)); } } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <returns></returns> public CommandStatus ReadDiskStructure(uint addr, byte layer, byte format, ref byte [] data) { if (m_logger != null) { string args = string.Empty; args += "addr=" + addr.ToString(); args += ", layer=" + layer.ToString(); args += ", format=" + format.ToString(); args += "ref byte[] data"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadDvdStructure(" + args + ")")); } using (Command cmd = new Command(ScsiCommandCode.ReadDvdStructure, 12, 2048, Command.CmdDirection.In, 60)) { cmd.SetCDB32(2, addr) ; // Address = 0 cmd.SetCDB8(6, layer); // Layer number = 0 cmd.SetCDB8(7, format); // Read manufacturing information cmd.SetCDB16(8, 2048); // Up to 2k of data CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; int len = data.GetLength(0); if (len > 2048) len = 2048; Marshal.Copy(cmd.GetBuffer(), data, 0, len); } return CommandStatus.Success; }
/// <summary> /// This method reads subheader CD data from a data mode 2 track /// </summary> /// <param name="sector">the sector # of the data to read</param> /// <param name="hdr">return subheader data</param> /// <returns></returns> public CommandStatus ReadCD(uint sector, out SubheaderData hdr) { hdr = null ; if (m_logger != null) { string args = sector.ToString() + ", out SubheaderData hdr"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadCD(" + args + ")")); } using (Command cmd = new Command(ScsiCommandCode.ReadCd, 12, 4, Command.CmdDirection.In, 10)) { cmd.SetCDB32(2, sector); cmd.SetCDB24(6, 1); cmd.SetCDB8(9, 0x40); // Header data only CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; hdr = new SubheaderData(cmd.GetBuffer(), cmd.BufferSize); } return CommandStatus.Success; }
/// <summary> /// Read the table of contents from the disk /// </summary> /// <param name="track">the track or session to find the TOC for</param> /// <param name="toc">a list return value containins a list of table of content entryies</param> /// <param name="mode">time versus lba mode</param> /// <returns></returns> public CommandStatus ReadToc(byte track, bool mode, out IList<TocEntry> toc) { ushort len; toc = null; if (m_logger != null) { string args = "info"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadToc(" + args + ")")); } using (Command cmd = new Command(ScsiCommandCode.ReadTocPmaAtip, 10, 16, Command.CmdDirection.In, 5 * 60)) { if (mode) cmd.SetCDB8(1, 2); cmd.SetCDB8(6, track); cmd.SetCDB16(7, 16); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer16(0); len += 2; } using (Command cmd = new Command(ScsiCommandCode.ReadTocPmaAtip, 10, len, Command.CmdDirection.In, 5 * 60)) { if (mode) cmd.SetCDB8(1, 2); cmd.SetCDB8(6, track); cmd.SetCDB16(7, len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; int offset = 4; toc = new List<TocEntry>(); while (offset + 8 <= len) { TocEntry entry = new TocEntry(cmd.GetBuffer(), offset, cmd.BufferSize, mode); toc.Add(entry); offset += 8; } } return CommandStatus.Success; }
/// <summary> /// Read the subchannel data from a series of sectors /// </summary> /// <param name="sector"></param> /// <param name="length"></param> /// <param name="data"></param> /// <param name="mode">the subchannel mode</param> /// <param name="timeout">timeout (in seconds)</param> /// <returns></returns> public CommandStatus ReadSubChannel(byte mode, uint sector, uint length, ref byte[] data, int timeout) { byte bytes_per_sector; if (m_logger != null) { string args = sector.ToString() + ", " + length.ToString() + ", data"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadSubChannel(" + args + ")")); } if (mode != 1 && mode != 2 && mode != 4) throw new Exception("invalid read mode for ReadSubchannel() call"); bytes_per_sector = 96; if (mode == 2) bytes_per_sector = 16; if (data.GetLength(0) < length * bytes_per_sector) throw new Exception("data buffer is not large enough to hold the data requested"); using (Command cmd = new Command(ScsiCommandCode.ReadCd, 12, (int)(length * bytes_per_sector), Command.CmdDirection.In, timeout)) { byte b = (byte)(1 << 2); cmd.SetCDB8(1, b); cmd.SetCDB32(2, sector); // The sector number to start with cmd.SetCDB24(6, length); // The length in sectors cmd.SetCDB8(10, mode); // Corrected, de-interleaved P - W data CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; Marshal.Copy(cmd.GetBuffer(), data, 0, (int)(length * bytes_per_sector)); } return CommandStatus.Success ; }
/// <summary> /// This method reads the ATIP information from a CD media /// </summary> /// <returns></returns> public CommandStatus ReadPMA(out byte[] data) { ushort len; data = null; if (m_logger != null) { string args = "info"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadFullToc(" + args + ")")); } using (Command cmd = new Command(ScsiCommandCode.ReadTocPmaAtip, 10, 320, Command.CmdDirection.In, 5 * 60)) { cmd.SetCDB8(1, 2); cmd.SetCDB8(2, 3); cmd.SetCDB16(7, 320); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer16(0); len += 2; if (len <= 320) { data = new byte[len]; Marshal.Copy(cmd.GetBuffer(), data, 0, len); return CommandStatus.Success; } } using (Command cmd = new Command(ScsiCommandCode.ReadTocPmaAtip, 10, len, Command.CmdDirection.In, 5 * 60)) { cmd.SetCDB8(2, 3); cmd.SetCDB16(7, len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; //info = new AtipInfo(cmd.GetBuffer(), len); data = new byte[len]; Marshal.Copy(cmd.GetBuffer(), data, 0, len); } return CommandStatus.Success; }
/// <summary> /// Read the subchannel data from a series of sectors /// </summary> /// <param name="mode">subchannel mode</param> /// <param name="track">track number</param> /// <param name="data">output buffer</param> /// <param name="offs">output buffer offset</param> /// <param name="timeout">timeout (in seconds)</param> /// <returns></returns> public CommandStatus ReadSubChannel42(byte mode, int track, ref byte[] data, int offs, int timeout) { if (m_logger != null) { m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadSubChannel42()")); } if (mode != 1 && mode != 2 && mode != 3) throw new Exception("invalid read mode for ReadSubchannel42() call"); int size = mode == 1 ? 16 : 24; if (offs + data.GetLength(0) < size) throw new Exception("data buffer is not large enough to hold the data requested"); using (Command cmd = new Command(ScsiCommandCode.ReadSubChannel, 10, size, Command.CmdDirection.In, timeout)) { // 42 00 40 01 00 00 00 00 10 00 //cmd.SetCDB8(1, 2); // MSF cmd.SetCDB8(2, 64); // SUBQ cmd.SetCDB8(3, mode); cmd.SetCDB8(6, (byte)track); cmd.SetCDB16(7, (ushort)size); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; Marshal.Copy(cmd.GetBuffer(), data, offs, size); } return CommandStatus.Success; }
/// <summary> /// /// </summary> /// <returns></returns> public CommandStatus RequestSense() { if (m_logger != null) { m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.RequestSense()")); } using (Command cmd = new Command(ScsiCommandCode.RequestSense, 6, 18, Command.CmdDirection.None, 5*60)) { cmd.SetCDB8(4, 18); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; m_sense_info = new byte[18]; Marshal.Copy(cmd.GetBuffer(), m_sense_info, 0, 18); } return CommandStatus.Success; }
/// <summary> /// Read the CD text information from the leadin using the ReadTocPmaAtip command form /// </summary> /// <param name="data"></param> /// <param name="_timeout"></param> /// <returns></returns> public CommandStatus ReadCDText(out byte [] data, int _timeout) { ushort len; if (m_logger != null) { string args = "info"; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.ReadCDText(" + args + ")")); } data = null; using (Command cmd = new Command(ScsiCommandCode.ReadTocPmaAtip, 10, 4, Command.CmdDirection.In, _timeout)) { cmd.SetCDB8(2, 5); // CDText info in leadin cmd.SetCDB16(7, 4); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; len = cmd.GetBuffer16(0); len += 2; if (len <= 4) { data = new byte[len]; Marshal.Copy(cmd.GetBuffer(), data, 0, len); return CommandStatus.Success; } } using (Command cmd = new Command(ScsiCommandCode.ReadTocPmaAtip, 10, len, Command.CmdDirection.In, _timeout)) { cmd.SetCDB8(2, 5); // CDText info in leadin cmd.SetCDB16(7, len); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; data = new byte[len]; Marshal.Copy(cmd.GetBuffer(), data, 0, len); } return CommandStatus.Success; }
private CommandStatus SendCommand32(Command cmd) { SCSI_PASS_THROUGH_DIRECT32 f = new SCSI_PASS_THROUGH_DIRECT32(); f.Length = m_scsi_request_size_32; f.CdbLength = (byte)cmd.GetCDBLength(); f.DataIn = 0; if (cmd.Direction == Command.CmdDirection.In) f.DataIn = 1; f.DataTransferLength = (uint)cmd.BufferSize; f.TimeOutValue = (uint)cmd.TimeOut; for (byte i = 0; i < f.CdbLength; i++) f.CdbData[i] = cmd.GetCDB(i); f.SenseInfoOffset = 48; f.SenseInfoLength = 24; uint total = (uint)Marshal.SizeOf(f); uint ret = 0; // Set the buffer field f.DataBuffer = cmd.GetBuffer(); // Send through ioctl field IntPtr pt = new IntPtr(&f); if (!Control(IOCTL_SCSI_PASS_THROUGH_DIRECT, pt, total, pt, total, ref ret, IntPtr.Zero)) { string str ; str = "IOCTL_SCSI_PASS_THROUGH_DIRECT failed - " + Win32ErrorToString(LastError); m_logger.LogMessage(new UserMessage(UserMessage.Category.Error, 0, str)); return CommandStatus.IoctlFailed; } m_scsi_status = f.ScsiStatus; if (f.SenseInfoLength != 0) { m_sense_info = new byte[f.SenseInfoLength]; for (int i = 0; i < f.SenseInfoLength; i++) m_sense_info[i] = f.SenseInfo[i]; } else m_sense_info = null; if (m_scsi_status != 0) { LogSenseInformation(cmd); return CommandStatus.DeviceFailed; } return CommandStatus.Success; }
/// <summary> /// This method sends the format unit command down to the SCSI device. /// </summary> /// <returns></returns> public CommandStatus FormatUnit(FormatParameterList plist) { if (m_logger != null) { string args = "plist" ; m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 8, "Bwg.Scsi.Device.FormatUnit(" + args + ")")); } using (Command cmd = new Command(ScsiCommandCode.FormatUnit, 6, (ushort)plist.Size, Command.CmdDirection.Out, 60*60)) { cmd.SetCDB8(1, 0x11); plist.FormatToMemory(cmd.GetBuffer()); CommandStatus st = SendCommand(cmd); if (st != CommandStatus.Success) return st; } return CommandStatus.Success; }