ided: add timeouts to loops and better debugging

This commit is contained in:
Jeremy Soller
2023-05-11 20:31:02 -06:00
parent 78b41c1d72
commit b05402e92b
3 changed files with 48 additions and 31 deletions
-16
View File
@@ -1,16 +0,0 @@
#[repr(u8)]
pub enum AtaCommand {
ReadPio = 0x20,
ReadPioExt = 0x24,
ReadDma = 0xC8,
ReadDmaExt = 0x25,
WritePio = 0x30,
WritePioExt = 0x34,
WriteDma = 0xCA,
WriteDmaExt = 0x35,
CacheFlush = 0xE7,
CacheFlushExt = 0xEA,
Packet = 0xA0,
IdentifyPacket = 0xA1,
Identify = 0xEC,
}
+45 -11
View File
@@ -2,13 +2,31 @@ use std::{
convert::TryInto,
sync::{Arc, Mutex},
thread,
time::{Duration, Instant},
};
use syscall::{
error::{Error, Result, EIO},
io::{Dma, Io, Pio, PhysBox, ReadOnly, WriteOnly},
};
use crate::ata::AtaCommand;
static TIMEOUT: Duration = Duration::new(1, 0);
#[repr(u8)]
pub enum AtaCommand {
ReadPio = 0x20,
ReadPioExt = 0x24,
ReadDma = 0xC8,
ReadDmaExt = 0x25,
WritePio = 0x30,
WritePioExt = 0x34,
WriteDma = 0xCA,
WriteDmaExt = 0x35,
CacheFlush = 0xE7,
CacheFlushExt = 0xEA,
Packet = 0xA0,
IdentifyPacket = 0xA1,
Identify = 0xEC,
}
#[repr(packed)]
struct PrdtEntry {
@@ -98,7 +116,7 @@ impl Channel {
Ok(status)
}
fn polling(&mut self, read: bool) -> Result<()> {
fn polling(&mut self, read: bool, line: u32) -> Result<()> {
/*
#define ATA_SR_BSY 0x80 // Busy
#define ATA_SR_DRDY 0x40 // Drive ready
@@ -115,17 +133,21 @@ impl Channel {
self.alt_status.read();
}
let start = Instant::now();
loop {
let status = self.check_status()?;
if status & 0x80 != 0 {
thread::yield_now();
} else {
if status & 0x80 == 0 {
if read && status & 0x08 == 0 {
log::error!("IDE data not ready");
log::error!("IDE read data not ready");
return Err(Error::new(EIO));
}
break;
}
if start.elapsed() >= TIMEOUT {
log::error!("line {} polling {} timeout with status 0x{:02X}", line, if read { "read" } else { "write" }, status);
return Err(Error::new(EIO));
}
thread::yield_now();
}
Ok(())
@@ -238,9 +260,10 @@ impl Disk for AtaDisk {
chan.busmaster_command.writef(1, true);
// Wait for transaction to finish
chan.polling(false)?;
chan.polling(false, line!())?;
// Wait for bus master to finish
let start = Instant::now();
let error = loop {
let status = chan.busmaster_status.read();
if status & 1 << 1 != 0 {
@@ -251,6 +274,11 @@ impl Disk for AtaDisk {
// Break when not busy and no error
break false;
}
if start.elapsed() >= TIMEOUT {
log::error!("busmaster read timeout with status 0x{:02X}", status);
return Err(Error::new(EIO));
}
thread::yield_now();
};
// Stop bus master
@@ -268,7 +296,7 @@ impl Disk for AtaDisk {
chunk.copy_from_slice(&chan.buf[..chunk.len()]);
} else {
for sector in 0..sectors {
chan.polling(true)?;
chan.polling(true, line!())?;
for i in 0..128 {
let data = chan.data32.read();
@@ -369,9 +397,10 @@ impl Disk for AtaDisk {
chan.busmaster_command.writef(1, true);
// Wait for transaction to finish
chan.polling(false)?;
chan.polling(false, line!())?;
// Wait for bus master to finish
let start = Instant::now();
let error = loop {
let status = chan.busmaster_status.read();
if status & 1 << 1 != 0 {
@@ -382,6 +411,11 @@ impl Disk for AtaDisk {
// Break when not busy and no error
break false;
}
if start.elapsed() >= TIMEOUT {
log::error!("busmaster write timeout with status 0x{:02X}", status);
return Err(Error::new(EIO));
}
thread::yield_now();
};
// Stop bus master
@@ -396,7 +430,7 @@ impl Disk for AtaDisk {
}
} else {
for sector in 0..sectors {
chan.polling(false)?;
chan.polling(false, line!())?;
for i in 0..128 {
chan.data32.write(
@@ -414,7 +448,7 @@ impl Disk for AtaDisk {
} else {
AtaCommand::CacheFlush as u8
});
chan.polling(false)?;
chan.polling(false, line!())?;
count += chunk.len();
}
+3 -4
View File
@@ -6,7 +6,7 @@ use std::{
io::{ErrorKind, Read, Write},
os::unix::io::{FromRawFd, RawFd},
sync::{Arc, Mutex},
thread::sleep,
thread::{self, sleep},
time::Duration,
};
use syscall::{
@@ -18,12 +18,10 @@ use syscall::{
};
use crate::{
ata::AtaCommand,
ide::{AtaDisk, Channel, Disk},
ide::{AtaCommand, AtaDisk, Channel, Disk},
scheme::DiskScheme,
};
pub mod ata;
pub mod ide;
pub mod scheme;
@@ -148,6 +146,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
// Not busy and data ready
break false;
}
thread::yield_now();
};
//TODO: probe ATAPI