Go back to polling ahcid to prevent hangs

This commit is contained in:
Jeremy Soller
2019-02-18 21:05:44 -07:00
parent 3f41225d78
commit c9e0dc4fd5
3 changed files with 86 additions and 59 deletions
+68 -47
View File
@@ -67,59 +67,80 @@ impl DiskATA {
BufferKind::Write(ref buffer) => (true, buffer.as_ptr() as usize, buffer.len()/512),
};
let mut request = match self.request_opt.take() {
Some(request) => if address == request.address && total_sectors == request.total_sectors {
// Keep servicing current request
request
} else {
// Have to wait for another request to finish
self.request_opt = Some(request);
return Ok(None);
},
None => {
// Create new request
Request {
address,
total_sectors,
sector: 0,
running_opt: None,
//TODO: Go back to interrupt magic
let use_interrupts = false;
loop {
let mut request = match self.request_opt.take() {
Some(request) => if address == request.address && total_sectors == request.total_sectors {
// Keep servicing current request
request
} else {
// Have to wait for another request to finish
self.request_opt = Some(request);
return Ok(None);
},
None => {
// Create new request
Request {
address,
total_sectors,
sector: 0,
running_opt: None,
}
}
}
};
// Finish a previously running request
if let Some(running) = request.running_opt.take() {
self.port.ata_stop(running.0)?;
if let BufferKind::Read(ref mut buffer) = buffer_kind {
unsafe { ptr::copy(self.buf.as_ptr(), buffer.as_mut_ptr().add(request.sector * 512), running.1 * 512); }
}
request.sector += running.1;
}
if request.sector < request.total_sectors {
// Start a new request
let sectors = if request.total_sectors - request.sector >= 255 {
255
} else {
request.total_sectors - request.sector
};
if let BufferKind::Write(ref buffer) = buffer_kind {
unsafe { ptr::copy(buffer.as_ptr().add(request.sector * 512), self.buf.as_mut_ptr(), sectors * 512); }
// Finish a previously running request
if let Some(running) = request.running_opt.take() {
if self.port.ata_running(running.0) {
// Continue waiting for request
request.running_opt = Some(running);
self.request_opt = Some(request);
if use_interrupts {
return Ok(None);
} else {
::std::thread::yield_now();
continue;
}
}
self.port.ata_stop(running.0)?;
if let BufferKind::Read(ref mut buffer) = buffer_kind {
unsafe { ptr::copy(self.buf.as_ptr(), buffer.as_mut_ptr().add(request.sector * 512), running.1 * 512); }
}
request.sector += running.1;
}
if let Some(slot) = self.port.ata_dma(block + request.sector as u64, sectors, write, &mut self.clb, &mut self.ctbas, &mut self.buf) {
request.running_opt = Some((slot, sectors));
if request.sector < request.total_sectors {
// Start a new request
let sectors = if request.total_sectors - request.sector >= 255 {
255
} else {
request.total_sectors - request.sector
};
if let BufferKind::Write(ref buffer) = buffer_kind {
unsafe { ptr::copy(buffer.as_ptr().add(request.sector * 512), self.buf.as_mut_ptr(), sectors * 512); }
}
if let Some(slot) = self.port.ata_dma(block + request.sector as u64, sectors, write, &mut self.clb, &mut self.ctbas, &mut self.buf) {
request.running_opt = Some((slot, sectors));
}
self.request_opt = Some(request);
if use_interrupts {
return Ok(None);
} else {
::std::thread::yield_now();
continue;
}
} else {
// Done
return Ok(Some(request.sector * 512));
}
self.request_opt = Some(request);
Ok(None)
} else {
// Done
Ok(Some(request.sector * 512))
}
}
}
+5 -1
View File
@@ -319,8 +319,12 @@ impl HbaPort {
}
}
pub fn ata_running(&self, slot: u32) -> bool {
(self.ci.readf(1 << slot) || self.tfd.readf(0x80)) && self.is.read() & HBA_PORT_IS_ERR == 0
}
pub fn ata_stop(&mut self, slot: u32) -> Result<()> {
while (self.ci.readf(1 << slot) || self.tfd.readf(0x80)) && self.is.read() & HBA_PORT_IS_ERR == 0 {
while self.ata_running(slot) {
thread::yield_now();
}
+13 -11
View File
@@ -84,23 +84,13 @@ fn main() {
todo.push(packet);
}
}
// let mut i = 0;
// while i < todo.len() {
// if let Some(a) = scheme.handle(&todo[i]) {
// let mut packet = todo.remove(i);
// packet.a = a;
// socket.write(&mut packet).expect("ahcid: failed to write disk scheme");
// } else {
// i += 1;
// }
// }
} else if event.id == irq_fd {
let mut irq = [0; 8];
if irq_file.read(&mut irq).expect("ahcid: failed to read irq file") >= irq.len() {
if scheme.irq() {
irq_file.write(&irq).expect("ahcid: failed to write irq file");
// Handle todos in order to finish previous packets if possible
let mut i = 0;
while i < todo.len() {
if let Some(a) = scheme.handle(&todo[i]) {
@@ -116,6 +106,18 @@ fn main() {
} else {
println!("Unknown event {}", event.id);
}
// Handle todos to start new packets if possible
let mut i = 0;
while i < todo.len() {
if let Some(a) = scheme.handle(&todo[i]) {
let mut packet = todo.remove(i);
packet.a = a;
socket.write(&mut packet).expect("ahcid: failed to write disk scheme");
} else {
i += 1;
}
}
}
}
unsafe { let _ = syscall::physunmap(address); }