From c9e0dc4fd5a81e2ec84c1cbc97e2ba3ad57cb795 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 18 Feb 2019 21:05:44 -0700 Subject: [PATCH] Go back to polling ahcid to prevent hangs --- ahcid/src/ahci/disk_ata.rs | 115 ++++++++++++++++++++++--------------- ahcid/src/ahci/hba.rs | 6 +- ahcid/src/main.rs | 24 ++++---- 3 files changed, 86 insertions(+), 59 deletions(-) diff --git a/ahcid/src/ahci/disk_ata.rs b/ahcid/src/ahci/disk_ata.rs index 468f47437b..03d51d838f 100644 --- a/ahcid/src/ahci/disk_ata.rs +++ b/ahcid/src/ahci/disk_ata.rs @@ -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)) } } } diff --git a/ahcid/src/ahci/hba.rs b/ahcid/src/ahci/hba.rs index 375615e4b5..35b57f2582 100644 --- a/ahcid/src/ahci/hba.rs +++ b/ahcid/src/ahci/hba.rs @@ -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(); } diff --git a/ahcid/src/main.rs b/ahcid/src/main.rs index 44596d8bbd..bcab6c4894 100644 --- a/ahcid/src/main.rs +++ b/ahcid/src/main.rs @@ -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); }