tape: use loaded media_type in format_media (instead of drive_density)
Required to format LTO4 media loaded in LTO5 drive). Also contains some SCSI code cleanups.
This commit is contained in:
parent
f2f43e1904
commit
33b8d7e5e8
@ -106,7 +106,7 @@ pub struct LtoTapeStatus {
|
|||||||
pub struct SgTape {
|
pub struct SgTape {
|
||||||
file: File,
|
file: File,
|
||||||
info: InquiryInfo,
|
info: InquiryInfo,
|
||||||
density_code: u8, // drive type
|
max_density_code: u8, // drive type
|
||||||
encryption_key_loaded: bool,
|
encryption_key_loaded: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,12 +125,12 @@ impl SgTape {
|
|||||||
bail!("not a tape device (peripheral_type = {})", info.peripheral_type);
|
bail!("not a tape device (peripheral_type = {})", info.peripheral_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
let density_code = report_density(&mut file)?;
|
let max_density_code = report_density(&mut file)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
file,
|
file,
|
||||||
info,
|
info,
|
||||||
density_code,
|
max_density_code,
|
||||||
encryption_key_loaded: false,
|
encryption_key_loaded: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -144,6 +144,10 @@ impl SgTape {
|
|||||||
&self.info
|
&self.info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn max_density_code(&self) -> u8 {
|
||||||
|
self.max_density_code
|
||||||
|
}
|
||||||
|
|
||||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<SgTape, Error> {
|
pub fn open<P: AsRef<Path>>(path: P) -> Result<SgTape, Error> {
|
||||||
// do not wait for media, use O_NONBLOCK
|
// do not wait for media, use O_NONBLOCK
|
||||||
let file = OpenOptions::new()
|
let file = OpenOptions::new()
|
||||||
@ -198,11 +202,14 @@ impl SgTape {
|
|||||||
|
|
||||||
self.rewind()?;
|
self.rewind()?;
|
||||||
|
|
||||||
|
// get info about loaded media first
|
||||||
|
let (head, _, _) = self.read_compression_page()?;
|
||||||
|
|
||||||
let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
|
let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
|
||||||
sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
|
sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
|
||||||
let mut cmd = Vec::new();
|
let mut cmd = Vec::new();
|
||||||
|
|
||||||
if self.density_code >= 0x58 { // FORMAT requires LTO5 or newer)
|
if head.medium_type >= 0x58 { // FORMAT requires LTO5 or newer)
|
||||||
cmd.extend(&[0x04, 0, 0, 0, 0, 0]);
|
cmd.extend(&[0x04, 0, 0, 0, 0, 0]);
|
||||||
sg_raw.do_command(&cmd)?;
|
sg_raw.do_command(&cmd)?;
|
||||||
if !fast {
|
if !fast {
|
||||||
@ -210,7 +217,6 @@ impl SgTape {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// try rewind/erase instead
|
// try rewind/erase instead
|
||||||
self.rewind()?;
|
|
||||||
self.erase_media(fast)?
|
self.erase_media(fast)?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,11 +626,7 @@ impl SgTape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(buffer_mode) = buffer_mode {
|
if let Some(buffer_mode) = buffer_mode {
|
||||||
let mut mode = head.flags3 & 0b1_000_1111;
|
head.set_buffer_mode(buffer_mode);
|
||||||
if buffer_mode {
|
|
||||||
mode |= 0b0_001_0000;
|
|
||||||
}
|
|
||||||
head.flags3 = mode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
@ -686,8 +688,8 @@ impl SgTape {
|
|||||||
|
|
||||||
Ok(LtoTapeStatus {
|
Ok(LtoTapeStatus {
|
||||||
block_length: block_descriptor.block_length(),
|
block_length: block_descriptor.block_length(),
|
||||||
write_protect: (head.flags3 & 0b1000_0000) != 0,
|
write_protect: head.write_protect(),
|
||||||
buffer_mode: (head.flags3 & 0b0111_0000) >> 4,
|
buffer_mode: head.buffer_mode(),
|
||||||
compression: page.compression_enabled(),
|
compression: page.compression_enabled(),
|
||||||
density_code: block_descriptor.density_code,
|
density_code: block_descriptor.density_code,
|
||||||
})
|
})
|
||||||
|
@ -223,12 +223,31 @@ pub struct InquiryInfo {
|
|||||||
#[derive(Endian, Debug, Copy, Clone)]
|
#[derive(Endian, Debug, Copy, Clone)]
|
||||||
pub struct ModeParameterHeader {
|
pub struct ModeParameterHeader {
|
||||||
pub mode_data_len: u16,
|
pub mode_data_len: u16,
|
||||||
pub medium_type: u8,
|
pub medium_type: u8, // Note: medium_type amd density_code are not the same
|
||||||
pub flags3: u8,
|
pub flags3: u8,
|
||||||
reserved4: [u8;2],
|
reserved4: [u8;2],
|
||||||
pub block_descriptior_len: u16,
|
pub block_descriptior_len: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ModeParameterHeader {
|
||||||
|
|
||||||
|
pub fn buffer_mode(&self) -> u8 {
|
||||||
|
(self.flags3 & 0b0111_0000) >> 4
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_buffer_mode(&mut self, buffer_mode: bool) {
|
||||||
|
let mut mode = self.flags3 & 0b1_000_1111;
|
||||||
|
if buffer_mode {
|
||||||
|
mode |= 0b0_001_0000;
|
||||||
|
}
|
||||||
|
self.flags3 = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_protect(&self) -> bool {
|
||||||
|
(self.flags3 & 0b1000_0000) != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
#[derive(Endian, Debug, Copy, Clone)]
|
#[derive(Endian, Debug, Copy, Clone)]
|
||||||
/// SCSI ModeBlockDescriptor for Tape devices
|
/// SCSI ModeBlockDescriptor for Tape devices
|
||||||
|
Loading…
Reference in New Issue
Block a user