diff --git a/rust/sys/denali/src/ahci/controller.rs b/rust/sys/denali/src/ahci/controller.rs index bfe52b0..a5ac3ca 100644 --- a/rust/sys/denali/src/ahci/controller.rs +++ b/rust/sys/denali/src/ahci/controller.rs @@ -1,6 +1,8 @@ use alloc::boxed::Box; -use alloc::rc::Rc; +use alloc::sync::Arc; use core::ffi::c_void; +use mammoth::sync::Mutex; +use mammoth::thread; use mammoth::{mem::MemoryRegion, thread::Thread, zion::ZError}; @@ -48,8 +50,6 @@ pub struct PciDeviceHeader { pub struct AhciController { pci_memory: MemoryRegion, hba_memory: MemoryRegion, - irq_port: Option, - irq_thread: Option>, ports: [Option>; 32], } @@ -68,18 +68,12 @@ impl AhciController { let mut controller = Self { pci_memory, hba_memory, - irq_port: None, - irq_thread: None, ports: [const { None }; 32], }; controller.init(); controller } - pub fn join(&self) -> Result<(), ZError> { - self.irq_thread.as_ref().unwrap().join() - } - fn init(&mut self) { self.ahci_hba().global_host_control.set_hba_reset(true); @@ -95,28 +89,11 @@ impl AhciController { mammoth::syscall::thread_sleep(50).unwrap(); - self.register_irq(); - self.init_ports().unwrap(); } - fn run_server(&self) -> Result, ZError> { - let thread_entry = |server_ptr: *const c_void| { - let server = unsafe { - (server_ptr as *mut Self) - .as_mut() - .expect("Failed to convert to server") - }; - server.irq_loop(); - }; - Thread::spawn( - thread_entry, - self as *const Self as *const core::ffi::c_void, - ) - } - - fn register_irq(&mut self) { - let irq_num = match self.pci_header().interrupt_pin { + fn irq_num(&self) -> u64 { + match self.pci_header().interrupt_pin { 1 => mammoth::zion::kZIrqPci1, 2 => mammoth::zion::kZIrqPci2, 3 => mammoth::zion::kZIrqPci3, @@ -125,29 +102,16 @@ impl AhciController { "Unrecognized pci interrupt pin {}", self.pci_header().interrupt_pin ), - }; - self.irq_port = Some(mammoth::port::PortServer::from_cap( - mammoth::syscall::register_irq(irq_num).unwrap(), - )); - - self.irq_thread = Some(self.run_server().unwrap()); - - self.ahci_hba() - .global_host_control - .set_interrupt_enable(true); + } } - fn irq_loop(&mut self) { - loop { - self.irq_port.as_ref().unwrap().recv_null().unwrap(); - - for i in 0..self.ahci_hba().capabilities.num_ports() { - let int_offset = 1 << i; - if (self.ahci_hba().interrupt_status & int_offset) == int_offset { - if let Some(port) = &mut self.ports[i as usize] { - port.handle_interrupt(); - self.ahci_hba().interrupt_status &= !int_offset; - } + fn handle_irq(&mut self) { + for i in 0..self.ahci_hba().capabilities.num_ports() { + let int_offset = 1 << i; + if (self.ahci_hba().interrupt_status & int_offset) == int_offset { + if let Some(port) = &mut self.ports[i as usize] { + port.handle_interrupt(); + self.ahci_hba().interrupt_status &= !int_offset; } } } @@ -214,6 +178,24 @@ impl AhciController { } } +pub fn spawn_irq_thread(controller: Arc>) -> thread::JoinHandle { + let irq_thread = move || { + let irq_num = controller.lock().irq_num(); + let irq_port = + mammoth::port::PortServer::from_cap(mammoth::syscall::register_irq(irq_num).unwrap()); + controller + .lock() + .ahci_hba() + .global_host_control + .set_interrupt_enable(true); + loop { + irq_port.recv_null().unwrap(); + controller.lock().handle_irq(); + } + }; + thread::spawn(irq_thread) +} + struct Command { command: SataCommand, lba: u64, @@ -253,7 +235,7 @@ impl From<&Command> for HostToDeviceRegisterFis { struct PortController<'a> { ahci_port_hba: &'a mut AhciPortHba, - command_slots: [Option>; 32], + command_slots: [Option>; 32], command_structures: MemoryRegion, } @@ -316,7 +298,7 @@ impl<'a> PortController<'a> { mammoth::debug!("Sector size: {:#0x}", sector_size); mammoth::debug!("LBA Count: {:#0x}", lba_count); }; - self.issue_command(Rc::from(Command::identify(callback)?))?; + self.issue_command(Arc::from(Command::identify(callback)?))?; } else { let sig = self.ahci_port_hba.signature; mammoth::debug!("Skipping non-sata sig: {:#0x}", sig); @@ -324,7 +306,7 @@ impl<'a> PortController<'a> { Ok(()) } - fn issue_command(&mut self, command: Rc) -> Result<(), ZError> { + fn issue_command(&mut self, command: Arc) -> Result<(), ZError> { let slot = self.select_slot()?; self.command_slots[slot] = Some(command.clone()); diff --git a/rust/sys/denali/src/ahci/mod.rs b/rust/sys/denali/src/ahci/mod.rs index ba0ede2..2fec39b 100644 --- a/rust/sys/denali/src/ahci/mod.rs +++ b/rust/sys/denali/src/ahci/mod.rs @@ -3,4 +3,5 @@ mod controller; mod hba; mod port; +pub use controller::spawn_irq_thread; pub use controller::AhciController; diff --git a/rust/sys/denali/src/bin/denali.rs b/rust/sys/denali/src/bin/denali.rs index 080fafe..ef4be28 100644 --- a/rust/sys/denali/src/bin/denali.rs +++ b/rust/sys/denali/src/bin/denali.rs @@ -3,9 +3,10 @@ extern crate alloc; -use mammoth::{define_entry, zion::z_err_t}; +use alloc::sync::Arc; +use mammoth::{define_entry, sync::Mutex, zion::z_err_t}; -use denali::ahci::AhciController; +use denali::ahci::{spawn_irq_thread, AhciController}; define_entry!(); @@ -19,12 +20,13 @@ extern "C" fn main() -> z_err_t { .get_ahci_info() .expect("Failed to get ahci info"); - let ahci_controller = AhciController::new( + let ahci_controller = Arc::new(Mutex::new(AhciController::new( mammoth::mem::MemoryRegion::from_cap(mammoth::cap::Capability::take(ahci_info.ahci_region)) .unwrap(), - ); + ))); - ahci_controller.join().unwrap(); + let thread = spawn_irq_thread(ahci_controller.clone()); + thread.join(); 0 }