diff --git a/rust/lib/mammoth/src/task/mod.rs b/rust/lib/mammoth/src/task/mod.rs index 0b23a67..aeba68b 100644 --- a/rust/lib/mammoth/src/task/mod.rs +++ b/rust/lib/mammoth/src/task/mod.rs @@ -28,11 +28,11 @@ pub struct Task { id: TaskId, // FIXME: This only needs to be sync because of the CURRENT_EXECUTOR // needing to be shared between threads. - future: Pin + Sync>>, + future: Pin + Sync + Send>>, } impl Task { - pub fn new(future: impl Future + Sync + 'static) -> Task { + pub fn new(future: impl Future + Sync + Send + 'static) -> Task { Task { id: TaskId::new(), future: Box::pin(future), diff --git a/rust/lib/yunq/src/server.rs b/rust/lib/yunq/src/server.rs index 57b844a..b4e3340 100644 --- a/rust/lib/yunq/src/server.rs +++ b/rust/lib/yunq/src/server.rs @@ -99,7 +99,7 @@ where mut byte_buffer: ByteBuffer<1024>, mut cap_buffer: Vec, reply_port_cap: Capability, - ) -> impl Future + Sync { + ) -> impl Future + Sync + Send { async move { let resp = self .handle_request(method, &mut byte_buffer, &mut cap_buffer) @@ -134,12 +134,14 @@ where method_number: u64, byte_buffer: &mut ByteBuffer<1024>, cap_buffer: &mut Vec, - ) -> impl Future> + Sync; + ) -> impl Future> + Sync + Send; } -pub fn spawn_async_server_thread(server: Arc, executor: Arc>) +pub fn spawn_async_server_thread(server: Arc, executor: Arc>) -> JoinHandle where T: AsyncYunqServer + Send + Sync + 'static, { - server.server_loop(executor); + thread::spawn(move || { + server.server_loop(executor); + }) } diff --git a/rust/sys/denali/src/ahci/controller.rs b/rust/sys/denali/src/ahci/controller.rs index 4453e13..e4f5e97 100644 --- a/rust/sys/denali/src/ahci/controller.rs +++ b/rust/sys/denali/src/ahci/controller.rs @@ -9,6 +9,7 @@ use alloc::boxed::Box; use alloc::sync::Arc; use mammoth::cap::Capability; use mammoth::sync::Mutex; +use mammoth::syscall; use mammoth::{mem, thread}; use mammoth::{mem::MemoryRegion, zion::ZError}; @@ -141,10 +142,12 @@ impl AhciController { for port in self.ports.iter().flatten() { let sig = port.get_signature(); if sig == 0x101 { - let command = Command::identify()?; + let mut command = Command::identify()?; mammoth::debug!("IDENT!"); port.issue_command(&command)?.await; - let ident = command.memory_region.slice::(); + let memory_region = + MemoryRegion::from_cap(Capability::take(command.release_mem_cap()))?; + let ident = memory_region.slice::(); let new_sector_size = if ident[106] & (1 << 12) != 0 { ident[117] as u32 | ((ident[118] as u32) << 16) } else { @@ -170,6 +173,18 @@ impl AhciController { } Ok(()) } + + pub async fn issue_command(&self, port_num: usize, command: &Command) -> Result<(), ZError> { + assert!(port_num < 32); + + self.ports[port_num] + .as_ref() + .ok_or(ZError::INVALID_ARGUMENT)? + .issue_command(command)? + .await; + + Ok(()) + } } pub fn spawn_irq_thread(controller: Arc) -> thread::JoinHandle { @@ -202,11 +217,11 @@ enum CommandStatus { struct CommandFuture { status: Arc>, - trigger: Box, + trigger: Box, } impl CommandFuture { - fn new(status: Arc>, trigger: Box) -> Self { + fn new(status: Arc>, trigger: Box) -> Self { Self { status, trigger } } } @@ -236,28 +251,44 @@ impl Future for CommandFuture { } } -struct Command { +pub struct Command { command: SataCommand, lba: u64, sector_cnt: u16, paddr: u64, - #[allow(dead_code)] // We need to own this even if we never access it. - memory_region: MemoryRegion, + memory_region: Option, } impl Command { pub fn identify() -> Result { - let (memory_region, paddr) = MemoryRegion::contiguous_physical(512)?; + let (memory_region, paddr) = syscall::memory_object_contiguous_physical(512)?; Ok(Self { command: SataCommand::IdentifyDevice, lba: 0, sector_cnt: 1, paddr, - memory_region, + memory_region: Some(memory_region), }) } + + pub fn read(lba: u64, lba_count: u16) -> Result { + let (memory_region, paddr) = + syscall::memory_object_contiguous_physical(512 * (lba_count as u64))?; + + Ok(Self { + command: SataCommand::DmaReadExt, + lba, + sector_cnt: lba_count, + paddr, + memory_region: Some(memory_region), + }) + } + + pub fn release_mem_cap(&mut self) -> u64 { + self.memory_region.take().unwrap().release() + } } impl From<&Command> for HostToDeviceRegisterFis { diff --git a/rust/sys/denali/src/ahci/mod.rs b/rust/sys/denali/src/ahci/mod.rs index e91e29c..a38f81f 100644 --- a/rust/sys/denali/src/ahci/mod.rs +++ b/rust/sys/denali/src/ahci/mod.rs @@ -6,3 +6,4 @@ mod port; pub use controller::identify_ports; pub use controller::spawn_irq_thread; pub use controller::AhciController; +pub use controller::Command; diff --git a/rust/sys/denali/src/bin/denali.rs b/rust/sys/denali/src/bin/denali.rs index 5adafc0..ee84990 100644 --- a/rust/sys/denali/src/bin/denali.rs +++ b/rust/sys/denali/src/bin/denali.rs @@ -11,7 +11,8 @@ use mammoth::{ zion::z_err_t, }; -use denali::ahci::{identify_ports, spawn_irq_thread, AhciController}; +use denali::ahci::{self, identify_ports, spawn_irq_thread, AhciController}; +use denali::{denali_server::DenaliServerImpl, AsyncDenaliServer}; define_entry!(); @@ -29,14 +30,25 @@ extern "C" fn main() -> z_err_t { ahci_info.ahci_region, ))); - let mut executor = Executor::new(); + let executor = Arc::new(Mutex::new(Executor::new())); - executor.spawn(Task::new(identify_ports(ahci_controller.clone()))); + executor + .clone() + .lock() + .spawn(Task::new(identify_ports(ahci_controller.clone()))); let thread = spawn_irq_thread(ahci_controller.clone()); - executor.run(); + let denali_server = + Arc::new(AsyncDenaliServer::new(DenaliServerImpl::new(ahci_controller.clone())).unwrap()); + + let server_thread = yunq::server::spawn_async_server_thread(denali_server, executor.clone()); + + executor.clone().lock().run(); thread.join().expect("Failed to wait on irq thread."); + server_thread + .join() + .expect("Failed to wait on server thread."); 0 } diff --git a/rust/sys/denali/src/denali_server.rs b/rust/sys/denali/src/denali_server.rs new file mode 100644 index 0000000..ebea567 --- /dev/null +++ b/rust/sys/denali/src/denali_server.rs @@ -0,0 +1,38 @@ +use alloc::sync::Arc; +use mammoth::zion::ZError; + +use crate::{ + ahci::{AhciController, Command}, + AsyncDenaliServerHandler, ReadManyRequest, ReadRequest, ReadResponse, +}; + +pub struct DenaliServerImpl { + ahci_controller: Arc, +} + +impl DenaliServerImpl { + pub fn new(controller: Arc) -> Self { + DenaliServerImpl { + ahci_controller: controller, + } + } +} + +impl AsyncDenaliServerHandler for DenaliServerImpl { + async fn read(&self, req: ReadRequest) -> Result { + let mut command = Command::read(req.block.lba, req.block.size as u16)?; + self.ahci_controller + .issue_command(req.device_id as usize, &command) + .await?; + + Ok(ReadResponse { + device_id: req.device_id, + size: req.block.size, + memory: command.release_mem_cap(), + }) + } + + async fn read_many(&self, req: ReadManyRequest) -> Result { + Err(ZError::UNIMPLEMENTED) + } +} diff --git a/rust/sys/denali/src/lib.rs b/rust/sys/denali/src/lib.rs index ee83829..0d06e8b 100644 --- a/rust/sys/denali/src/lib.rs +++ b/rust/sys/denali/src/lib.rs @@ -5,3 +5,4 @@ use core::include; include!(concat!(env!("OUT_DIR"), "/yunq.rs")); pub mod ahci; +pub mod denali_server;