Clean pipeline: one open, one init, no double-init
- Removed open_unlocked() — open() is the only entry - Removed redundant init() call from open_title() - init() called once in open(), handles everything - Each function does one thing: open→init→scan→read
This commit is contained in:
+1
-3
@@ -798,9 +798,7 @@ impl Disc {
|
||||
detail: format!("title index {} out of range (have {})", title_idx, self.titles.len()),
|
||||
})?;
|
||||
|
||||
if !session.is_unlocked() {
|
||||
let _ = session.init();
|
||||
}
|
||||
// init() already called by DriveSession::open(). No re-init needed.
|
||||
|
||||
let speed_cdb = crate::scsi::build_set_cd_speed(0xFFFF);
|
||||
let mut dummy = [0u8; 0];
|
||||
|
||||
+4
-14
@@ -30,10 +30,11 @@ pub struct DriveSession {
|
||||
}
|
||||
|
||||
impl DriveSession {
|
||||
/// Open a drive — identify, wait for disc, and unlock for raw reads.
|
||||
///
|
||||
/// This is the standard entry point. After `open()`, the drive is
|
||||
/// ready for scanning and content reads.
|
||||
/// This is the only entry point. After `open()`, the drive is
|
||||
/// ready for scanning and content reads. init() handles everything:
|
||||
/// unlock, firmware upload if needed, calibration, registers.
|
||||
/// Called once per session. Non-fatal if init fails (BD works without it).
|
||||
pub fn open(device: &Path) -> Result<Self> {
|
||||
let mut session = Self::open_no_unlock(device)?;
|
||||
session.wait_ready()?;
|
||||
@@ -41,17 +42,6 @@ impl DriveSession {
|
||||
Ok(session)
|
||||
}
|
||||
|
||||
/// Open a drive and immediately init for raw reads.
|
||||
///
|
||||
/// Use this when you need raw disc access without AACS (e.g. capture,
|
||||
/// sector dumps). Skips AACS authentication — cannot be done after init.
|
||||
pub fn open_unlocked(device: &Path) -> Result<Self> {
|
||||
let mut session = Self::open_no_unlock(device)?;
|
||||
session.wait_ready()?;
|
||||
let _ = session.init();
|
||||
Ok(session)
|
||||
}
|
||||
|
||||
/// Open a drive — identify only, no wait, no unlock.
|
||||
///
|
||||
/// Low-level entry point. Caller is responsible for wait_ready()
|
||||
|
||||
+15
-10
@@ -463,11 +463,21 @@ impl Platform for Mt1959 {
|
||||
/// Phase 5: cmd 9 × 6 retries (status)
|
||||
fn init(&mut self, scsi: &mut dyn ScsiTransport) -> Result<()> {
|
||||
// Phase 1: Unlock + firmware upload (6 retries)
|
||||
//
|
||||
// Three unlock outcomes:
|
||||
// Ok → warm drive, firmware loaded, skip to calibrate
|
||||
// Err(other) → cold drive or SCSI error, try load_firmware
|
||||
let mut unlocked = false;
|
||||
for _attempt in 0..6 {
|
||||
match self.unlock(scsi) {
|
||||
Ok(_) => { unlocked = true; break; }
|
||||
Err(Error::SignatureMismatch { .. }) => {
|
||||
return Err(Error::UnlockFailed {
|
||||
detail: "signature mismatch — wrong profile for this drive".into(),
|
||||
});
|
||||
}
|
||||
Err(_) => {
|
||||
// Cold boot or SCSI error — try uploading firmware
|
||||
if self.load_firmware(scsi).is_ok() {
|
||||
unlocked = true;
|
||||
break;
|
||||
@@ -493,17 +503,12 @@ impl Platform for Mt1959 {
|
||||
return Err(Error::ScsiError { opcode: 0x3C, status: 0xFF, sense_key: 0 });
|
||||
}
|
||||
|
||||
// If fails: cmd 5 fallback (keepalive)
|
||||
// In our context: this fetches a display string, not critical for reads
|
||||
let _ = self.probe(scsi, 0x00, 0, 0x3FF);
|
||||
// Phase 3: Read registers — non-fatal
|
||||
// x86 retries 5×, but we do a single attempt each. Not required for reads.
|
||||
let _ = self.read_register_a(scsi);
|
||||
let _ = self.read_register_b(scsi);
|
||||
|
||||
for _attempt in 0..5 {
|
||||
let a_ok = self.read_register_a(scsi).is_ok();
|
||||
let b_ok = self.read_register_b(scsi).is_ok();
|
||||
if a_ok && b_ok { break; }
|
||||
}
|
||||
|
||||
// Phase 5: Status — non-fatal, single attempt
|
||||
// Phase 4: Status — non-fatal, single attempt
|
||||
// Some drives reject sub_cmd 0x13. Not required for reads.
|
||||
let _ = self.status(scsi);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user