diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml deleted file mode 100644 index bf7a604..0000000 --- a/.forgejo/workflows/ci.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Check - -on: - push: - branches: [main] - pull_request: - branches: [main] - -env: - # Should speed up builds. - CARGO_INCREMENTAL: 0 - # Should reduce the size of ./target to improve cache load/store. - CARGO_PROFILE_TEST_DEBUG: 0 - -jobs: - check: - name: Check Rust - runs-on: docker - - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - - - name: Install Rust - uses: https://codeberg.org/wackbyte/rust-toolchain@trunk - with: - toolchain: nightly-2025-10-02 - components: rustfmt, clippy, rust-src - - name: Cache - uses: https://github.com/Swatinem/rust-cache@v2 - with: - # Don't cache ~/.cargo/bin since we restore the cache after we install things there - cache-bin: "false" - workspaces: "backend" - - name: "Check Format" - run: cargo fmt --check - working-directory: rust - - name: "Lint" - run: | - rustup component add clippy - cargo clippy --locked -- -D warnings - working-directory: rust diff --git a/rust-toolchain.toml b/rust-toolchain.toml index f7acab6..66768f4 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] channel = "nightly-2025-10-02" -components = ["rustfmt", "rust-analyzer", "clippy", "rust-src"] +components = ["rustfmt", "rust-analyzer"] diff --git a/rust/lib/client/voyageurs_client/src/listener.rs b/rust/lib/client/voyageurs_client/src/listener.rs index 89e40b6..1912b88 100644 --- a/rust/lib/client/voyageurs_client/src/listener.rs +++ b/rust/lib/client/voyageurs_client/src/listener.rs @@ -7,7 +7,7 @@ use mammoth::thread; #[allow(dead_code)] #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] enum Keycode { - Unknown = 0x0, + UnknownKeycode = 0x0, A = 0x1, B = 0x2, @@ -135,7 +135,7 @@ impl Keycode { 0x37 => Keycode::Period, 0x38 => Keycode::FSlash, 0x39 => Keycode::Esc, - _ => Keycode::Unknown, + _ => Keycode::UnknownKeycode, } } } diff --git a/rust/lib/fs/ext2/src/ext2_driver.rs b/rust/lib/fs/ext2/src/ext2_driver.rs index 0997b62..96bb858 100644 --- a/rust/lib/fs/ext2/src/ext2_driver.rs +++ b/rust/lib/fs/ext2/src/ext2_driver.rs @@ -94,7 +94,7 @@ impl Ext2Driver { /// Updates the cached inode tables to contain the inode table for /// a specific group. fn populate_inode_table_if_none(&mut self, block_group_num: usize) { - if self.inode_table_map[block_group_num].is_none() { + if let None = self.inode_table_map[block_group_num] { debug!( "Cache MISS on inode table for block_group {}", block_group_num @@ -148,15 +148,17 @@ impl Ext2Driver { let dbl_indr_block_mem = MemoryRegion::from_cap(self.reader.read(block_num, 1).unwrap()).unwrap(); - let dbl_indr_blocks: &[u32] = &dbl_indr_block_mem.slice()[0..num_dbl_indr]; + let dbl_indr_blocks: &[u32] = dbl_indr_block_mem.slice(); let mut blocks_to_read = Vec::new(); - for (i, dbl_indr_block) in dbl_indr_blocks.iter().enumerate() { + for i in 0..num_dbl_indr { let num_blocks_in_single = min(num_blocks - (256 * i), 256); blocks_to_read.append( - &mut self - .get_blocks_from_single_indirect(*dbl_indr_block as u64, num_blocks_in_single), + &mut self.get_blocks_from_single_indirect( + dbl_indr_blocks[i] as u64, + num_blocks_in_single, + ), ); } @@ -174,7 +176,7 @@ impl Ext2Driver { let mut blocks = Vec::new(); - for block in iter { + while let Some(block) = iter.next() { if block as u64 == (curr_block.lba + curr_block.size) { curr_block.size += 1; } else { diff --git a/rust/lib/fs/ext2/src/types.rs b/rust/lib/fs/ext2/src/types.rs index fd1f59b..7aa3d2b 100644 --- a/rust/lib/fs/ext2/src/types.rs +++ b/rust/lib/fs/ext2/src/types.rs @@ -111,9 +111,7 @@ pub struct Inode { const _: () = assert!(size_of::() == 128); -#[allow(dead_code)] pub const EXT2_FT_FILE: u8 = 0x1; -#[allow(dead_code)] pub const EXT2_FT_DIR: u8 = 0x2; #[repr(C, packed)] diff --git a/rust/lib/mammoth/src/cap_syscall.rs b/rust/lib/mammoth/src/cap_syscall.rs index b820bdc..eb9567a 100644 --- a/rust/lib/mammoth/src/cap_syscall.rs +++ b/rust/lib/mammoth/src/cap_syscall.rs @@ -2,6 +2,7 @@ use core::ffi::c_void; use crate::zion::{self, z_cap_t, ZError}; +#[must_use] fn syscall(id: u64, req: &T) -> Result<(), ZError> { unsafe { let resp = zion::SysCall1(id, req as *const T as *const c_void); diff --git a/rust/lib/mammoth/src/elf.rs b/rust/lib/mammoth/src/elf.rs index 28b636f..dd33876 100644 --- a/rust/lib/mammoth/src/elf.rs +++ b/rust/lib/mammoth/src/elf.rs @@ -1,4 +1,5 @@ use crate::cap::Capability; +use crate::debug; use crate::init; use crate::syscall; use crate::zion::ZError; @@ -236,7 +237,7 @@ fn load_program_segment( let page_offset = prog_header.vaddr & 0xFFF; let mem_size = page_offset + prog_header.mem_size; - let mut mem_object = crate::mem::MemoryRegion::new(mem_size)?; + let mem_object = crate::mem::MemoryRegion::new(mem_size)?; mem_object.zero_region(); diff --git a/rust/lib/mammoth/src/init.rs b/rust/lib/mammoth/src/init.rs index c190ad1..556cf24 100644 --- a/rust/lib/mammoth/src/init.rs +++ b/rust/lib/mammoth/src/init.rs @@ -28,7 +28,7 @@ pub fn parse_init_port(port_cap: z_cap_t) { let mut caps: [u64; 1] = [0]; let resp = syscall::port_poll(&init_port, &mut bytes, &mut caps); - if resp.is_err() { + if let Err(_) = resp { break; } diff --git a/rust/lib/mammoth/src/macros.rs b/rust/lib/mammoth/src/macros.rs index 3fc64c5..c977a91 100644 --- a/rust/lib/mammoth/src/macros.rs +++ b/rust/lib/mammoth/src/macros.rs @@ -2,20 +2,21 @@ use alloc::string::String; use alloc::vec::Vec; use core::fmt; -#[derive(Default)] pub struct Writer { int_vec: Vec, } impl Writer { pub fn new() -> Self { - Writer::default() + Self { + int_vec: Vec::new(), + } } } -impl From for String { - fn from(value: Writer) -> Self { - String::from_utf8(value.int_vec).expect("Failed to convert") +impl Into for Writer { + fn into(self) -> String { + String::from_utf8(self.int_vec).expect("Failed to convert") } } diff --git a/rust/lib/mammoth/src/mem.rs b/rust/lib/mammoth/src/mem.rs index d10e65d..a203c74 100644 --- a/rust/lib/mammoth/src/mem.rs +++ b/rust/lib/mammoth/src/mem.rs @@ -3,6 +3,7 @@ use crate::syscall; use crate::zion::ZError; use alloc::slice; use core::fmt::Debug; +use core::ops::Deref; use core::ptr::{addr_of, addr_of_mut, read_volatile, write_volatile, NonNull}; #[cfg(feature = "hosted")] @@ -90,7 +91,7 @@ impl MemoryRegion { } } - pub fn mut_slice(&mut self) -> &mut [T] { + pub fn mut_slice(&self) -> &mut [T] { unsafe { slice::from_raw_parts_mut( self.virt_addr as *mut T, @@ -99,7 +100,7 @@ impl MemoryRegion { } } - pub fn zero_region(&mut self) { + pub fn zero_region(&self) { for i in self.mut_slice() { *i = 0; } @@ -117,9 +118,8 @@ impl MemoryRegion { /// Creates a reference from a given offset. /// - /// # Safety - /// - Caller must ensure that the memory pointed to by this - /// pointer must not get mutated while the reference exists. + /// SAFETY: Caller must ensure that the memory pointed to by this + /// pointer must not get mutated while the reference exists. pub unsafe fn as_ref_at_offset(&self, offset: usize) -> &T { let ptr: *const T = self.raw_ptr_at_offset(offset as u64); assert!(ptr.is_aligned(), ""); @@ -132,10 +132,9 @@ impl MemoryRegion { /// Creates a reference from a given offset. /// - /// # Safety - /// - Caller must ensure that this is the only reference to the memory pointed - /// to by this pointer. - pub unsafe fn as_mut_ref_at_offset(&mut self, offset: usize) -> &mut T { + /// SAFETY: Caller must ensure that this is the only reference to the memory pointed + /// to by this pointer. + pub unsafe fn as_mut_ref_at_offset(&self, offset: usize) -> &mut T { let ptr: *const T = self.raw_ptr_at_offset(offset as u64); assert!(ptr.is_aligned(), ""); // SAFETY: diff --git a/rust/lib/mammoth/src/physical_box.rs b/rust/lib/mammoth/src/physical_box.rs index af68cba..963b6ec 100644 --- a/rust/lib/mammoth/src/physical_box.rs +++ b/rust/lib/mammoth/src/physical_box.rs @@ -89,7 +89,7 @@ impl PhysicalBox<[T]> { } } - pub fn from_vec(vec: Vec) -> Self { + pub fn from_vec(mut vec: Vec) -> Self { let len = vec.len(); let layout = core::alloc::Layout::array::(len).expect("Layout overflow"); @@ -117,10 +117,6 @@ impl PhysicalBox<[T]> { pub fn len(&self) -> usize { (**self).len() } - - pub fn is_empty(&self) -> bool { - self.len() == 0 - } } impl Index for PhysicalBox<[T]> diff --git a/rust/lib/mammoth/src/sync.rs b/rust/lib/mammoth/src/sync.rs index f435e32..0ee5fea 100644 --- a/rust/lib/mammoth/src/sync.rs +++ b/rust/lib/mammoth/src/sync.rs @@ -50,7 +50,7 @@ impl DerefMut for MutexGuard<'_, T> { } } -impl<'a, T> Mutex { +impl Mutex { pub fn new(data: T) -> Mutex { Mutex { cap: syscall::mutex_create().unwrap(), @@ -58,7 +58,7 @@ impl<'a, T> Mutex { } } - pub fn lock(&'a self) -> MutexGuard<'a, T> { + pub fn lock(&self) -> MutexGuard { syscall::mutex_lock(&self.cap).unwrap(); MutexGuard { mutex: self } @@ -70,12 +70,3 @@ impl Drop for MutexGuard<'_, T> { syscall::mutex_release(&self.mutex.cap).unwrap(); } } - -impl Default for Mutex -where - T: Default, -{ - fn default() -> Self { - Self::new(T::default()) - } -} diff --git a/rust/lib/mammoth/src/syscall.rs b/rust/lib/mammoth/src/syscall.rs index bab76ca..2691458 100644 --- a/rust/lib/mammoth/src/syscall.rs +++ b/rust/lib/mammoth/src/syscall.rs @@ -9,6 +9,7 @@ use core::ffi::c_void; #[cfg(feature = "hosted")] use core::panic::PanicInfo; +#[must_use] fn syscall(id: u64, req: &T) -> Result<(), ZError> { unsafe { let resp = zion::SysCall1(id, req as *const T as *const c_void); diff --git a/rust/lib/mammoth/src/task/mod.rs b/rust/lib/mammoth/src/task/mod.rs index fee1a9d..92164ec 100644 --- a/rust/lib/mammoth/src/task/mod.rs +++ b/rust/lib/mammoth/src/task/mod.rs @@ -48,7 +48,7 @@ struct TaskWaker { } impl TaskWaker { - fn create_waker(task_id: TaskId, task_queue: Arc>>) -> Waker { + fn new(task_id: TaskId, task_queue: Arc>>) -> Waker { Waker::from(Arc::new(TaskWaker { task_id, task_queue, @@ -69,7 +69,6 @@ impl Wake for TaskWaker { } } -#[derive(Default)] pub struct Executor { tasks: Arc>>, // TODO: Consider a better datastructure for this. @@ -79,7 +78,11 @@ pub struct Executor { impl Executor { pub fn new() -> Executor { - Executor::default() + Executor { + tasks: Arc::new(Mutex::new(BTreeMap::new())), + task_queue: Arc::new(Mutex::new(VecDeque::new())), + waker_cache: BTreeMap::new(), + } } pub fn spawn(&mut self, task: Task) { @@ -97,7 +100,7 @@ impl Executor { let waker = self .waker_cache .entry(task_id) - .or_insert_with(|| TaskWaker::create_waker(task_id, self.task_queue.clone())); + .or_insert_with(|| TaskWaker::new(task_id, self.task_queue.clone())); let mut ctx = Context::from_waker(waker); match task.poll(&mut ctx) { Poll::Ready(()) => { diff --git a/rust/lib/mammoth/src/thread.rs b/rust/lib/mammoth/src/thread.rs index aeb4b27..99032be 100644 --- a/rust/lib/mammoth/src/thread.rs +++ b/rust/lib/mammoth/src/thread.rs @@ -40,7 +40,7 @@ where let raw_main = Box::into_raw(Box::new(main)); let proc_cap = Capability::take_copy(unsafe { crate::init::SELF_PROC_CAP }).unwrap(); let cap = syscall::thread_create(&proc_cap).unwrap(); - syscall::thread_start(&cap, entry_point as usize as u64, raw_main as u64, 0).unwrap(); + syscall::thread_start(&cap, entry_point as u64, raw_main as u64, 0).unwrap(); JoinHandle { cap } } diff --git a/rust/lib/pci/src/device.rs b/rust/lib/pci/src/device.rs index d74cb82..948cd04 100644 --- a/rust/lib/pci/src/device.rs +++ b/rust/lib/pci/src/device.rs @@ -2,7 +2,8 @@ use alloc::vec::Vec; use mammoth::{cap::Capability, mem::MemoryRegion, syscall, zion::ZError}; use crate::header::{ - PciCapabilityPointer, PciDeviceHeader, PciHeaderType, PciMsiCapability, get_header_type, + PciCapabilityPointer, PciDeviceHeader, PciHeaderType, PciMsiCapability, PciMsiControl, + get_header_type, }; pub struct PciDevice { @@ -10,7 +11,7 @@ pub struct PciDevice { } impl PciDevice { - pub fn from(memory_region: MemoryRegion) -> Result { + pub fn from(mut memory_region: MemoryRegion) -> Result { match get_header_type(&memory_region)? { PciHeaderType::Device => {} t => { diff --git a/rust/lib/yellowstone/src/lib.rs b/rust/lib/yellowstone/src/lib.rs index ffdc267..76659ef 100644 --- a/rust/lib/yellowstone/src/lib.rs +++ b/rust/lib/yellowstone/src/lib.rs @@ -10,12 +10,10 @@ static mut YELLOWSTONE_INIT: Option = None; pub fn from_init_endpoint() -> &'static mut YellowstoneClient { unsafe { - #[allow(static_mut_refs)] - if YELLOWSTONE_INIT.is_none() { + if let None = YELLOWSTONE_INIT { YELLOWSTONE_INIT = Some(YellowstoneClient::new(Capability::take(INIT_ENDPOINT))); } - #[allow(static_mut_refs)] YELLOWSTONE_INIT.as_mut().unwrap() } } diff --git a/rust/lib/yunq-test/src/lib.rs b/rust/lib/yunq-test/src/lib.rs index 9af3d55..1a3c3ec 100644 --- a/rust/lib/yunq-test/src/lib.rs +++ b/rust/lib/yunq-test/src/lib.rs @@ -12,11 +12,7 @@ mod tests { #[test] fn basic_serialization() -> Result<(), ZError> { - let basic = Basic { - unsigned_int: 82, - signed_int: -1234, - strn: "abc".to_string(), - }; + let basic = Basic { unsigned_int: 82, signed_int: -1234, strn: "abc".to_string() }; let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); @@ -31,17 +27,13 @@ mod tests { #[test] fn basic_serialization_as_request() -> Result<(), ZError> { - let basic = Basic { - unsigned_int: 82, - signed_int: -1234, - strn: "abc".to_string(), - }; + let basic = Basic { unsigned_int: 82, signed_int: -1234, strn: "abc".to_string() }; let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); let req_id = 12; basic.serialize_as_request(req_id, &mut buf, &mut caps)?; - + assert!(buf.at::(8)? == req_id); let parsed = Basic::parse_from_request(&buf, &caps)?; @@ -58,7 +50,7 @@ mod tests { let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); cap.serialize(&mut buf, 0, &mut caps)?; - + assert!(caps.len() == 1); assert!(caps[0] == cap_id); @@ -71,14 +63,12 @@ mod tests { #[test] fn repeated_serialization() -> Result<(), ZError> { - let rep = Repeated { - unsigned_ints: vec![0, 1, 3], - }; + let rep = Repeated { unsigned_ints: vec![0, 1, 3],}; let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); rep.serialize(&mut buf, 0, &mut caps)?; - + let parsed = Repeated::parse(&buf, 0, &caps)?; assert!(parsed == rep); @@ -89,21 +79,18 @@ mod tests { #[test] fn nested_serialization() -> Result<(), ZError> { let nested = Nested { - basic: Basic { - unsigned_int: 82, - signed_int: -1234, - strn: "abc".to_string(), - }, - cap1: Cap { cap: 37 }, - cap2: Cap { cap: 39 }, + basic: Basic { unsigned_int: 82, signed_int: -1234, strn: "abc".to_string() }, + cap1: Cap { cap: 37}, + cap2: Cap { cap: 39}, }; let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); nested.serialize(&mut buf, 0, &mut caps)?; - + let parsed = Nested::parse(&buf, 0, &caps)?; + assert!(parsed == nested); Ok(()) @@ -112,29 +99,23 @@ mod tests { #[test] fn repeated_nested_serialization() -> Result<(), ZError> { let nested = RepeatedNested { - basics: vec![ - Basic { - unsigned_int: 82, - signed_int: -1234, - strn: "abc".to_string(), - }, - Basic { - unsigned_int: 21, - signed_int: -8, - strn: "def".to_string(), - }, - ], - caps: vec![Cap { cap: 123 }, Cap { cap: 12343 }], + basics: vec![Basic { unsigned_int: 82, signed_int: -1234, strn: "abc".to_string(),}, + Basic { unsigned_int: 21, signed_int: -8, strn: "def".to_string(), },], + caps: vec![Cap{ cap: 123}, Cap {cap: 12343}], }; let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); nested.serialize(&mut buf, 0, &mut caps)?; - + let parsed = RepeatedNested::parse(&buf, 0, &caps)?; + assert!(parsed == nested); + Ok(()) } + + } diff --git a/rust/lib/yunq/src/buffer.rs b/rust/lib/yunq/src/buffer.rs index 7966337..c3b0b18 100644 --- a/rust/lib/yunq/src/buffer.rs +++ b/rust/lib/yunq/src/buffer.rs @@ -5,19 +5,12 @@ pub struct ByteBuffer { buffer: Box<[u8; N]>, } -impl Default for ByteBuffer { - fn default() -> Self { +impl ByteBuffer { + pub fn new() -> Self { Self { buffer: Box::new([0; N]), } } -} - -impl ByteBuffer { - pub fn new() -> Self { - ByteBuffer::default() - } - pub fn size(&self) -> u64 { N as u64 } @@ -61,7 +54,7 @@ impl ByteBuffer { if (len + offset) > N { return Err(ZError::BUFFER_SIZE); } - alloc::str::from_utf8(&self.buffer[offset..offset + len]) - .map_err(|_| ZError::INVALID_ARGUMENT) + Ok(alloc::str::from_utf8(&self.buffer[offset..offset + len]) + .map_err(|_| ZError::INVALID_ARGUMENT)?) } } diff --git a/rust/lib/yunq/src/client.rs b/rust/lib/yunq/src/client.rs index c4c45b8..e90698e 100644 --- a/rust/lib/yunq/src/client.rs +++ b/rust/lib/yunq/src/client.rs @@ -34,5 +34,5 @@ pub fn call_endpoint( return Err(ZError::from(resp_code)); } - Resp::parse_from_request(byte_buffer, &cap_buffer) + Ok(Resp::parse_from_request(&byte_buffer, &cap_buffer)?) } diff --git a/rust/lib/yunq/src/message.rs b/rust/lib/yunq/src/message.rs index 568916f..d1fc6a5 100644 --- a/rust/lib/yunq/src/message.rs +++ b/rust/lib/yunq/src/message.rs @@ -28,7 +28,7 @@ pub fn parse_repeated_message( buf: &ByteBuffer, mut offset: usize, len: usize, - caps: &[z_cap_t], + caps: &Vec, ) -> Result, ZError> { let mut repeated = Vec::new(); for _ in 0..len { @@ -43,18 +43,18 @@ pub fn parse_repeated_message( pub fn serialize_repeated( buf: &mut ByteBuffer, offset: usize, - data: &[T], + data: &Vec, ) -> Result { - for (i, val) in data.iter().enumerate() { - buf.write_at(offset + (i * size_of::()), val)?; + for i in 0..data.len() { + buf.write_at(offset + (i * size_of::()), data[i])?; } - Ok(offset + size_of_val(data)) + Ok(offset + (data.len() * size_of::())) } pub fn serialize_repeated_message( buf: &mut ByteBuffer, mut offset: usize, - data: &[T], + data: &Vec, caps: &mut Vec, ) -> Result { for item in data { @@ -76,14 +76,14 @@ pub trait YunqMessage { fn parse( buf: &ByteBuffer, offset: usize, - caps: &[z_cap_t], + caps: &Vec, ) -> Result where Self: Sized; fn parse_from_request( buf: &ByteBuffer, - caps: &[z_cap_t], + caps: &Vec, ) -> Result where Self: Sized, @@ -92,7 +92,7 @@ pub trait YunqMessage { return Err(ZError::INVALID_RESPONSE); } - Self::parse(buf, 16, caps) + Ok(Self::parse(&buf, 16, &caps)?) } fn serialize( @@ -109,7 +109,7 @@ pub trait YunqMessage { caps: &mut Vec, ) -> Result { buf.write_at(0, SENTINEL)?; - buf.write_at(8, request_id)?; + buf.write_at(8, request_id as u64)?; let length = self.serialize(buf, 16, caps)?; @@ -125,7 +125,7 @@ impl YunqMessage for Empty { fn parse( _buf: &ByteBuffer, _offset: usize, - _caps: &[z_cap_t], + _caps: &Vec, ) -> Result where Self: Sized, diff --git a/rust/lib/yunq/src/server.rs b/rust/lib/yunq/src/server.rs index cdfe418..a5ded0b 100644 --- a/rust/lib/yunq/src/server.rs +++ b/rust/lib/yunq/src/server.rs @@ -37,7 +37,7 @@ pub trait YunqServer { .expect("Failed to reply"), Err(err) => { crate::message::serialize_error(&mut byte_buffer, err); - syscall::reply_port_send(reply_port_cap, byte_buffer.slice(0x10), &[]) + syscall::reply_port_send(reply_port_cap, &byte_buffer.slice(0x10), &[]) .expect("Failed to reply w/ error") } } @@ -84,11 +84,11 @@ where .at::(8) .expect("Failed to access request length."); let self_clone = self.clone(); - spawner.spawn(Task::new(async move { + spawner.spawn(Task::new((async move || { self_clone .handle_request_and_response(method, byte_buffer, cap_buffer, reply_port_cap) - .await - })); + .await; + })())); } } @@ -113,10 +113,12 @@ where .expect("Failed to reply"), Err(err) => { crate::message::serialize_error(&mut byte_buffer, err); - syscall::reply_port_send(reply_port_cap, byte_buffer.slice(0x10), &[]) + syscall::reply_port_send(reply_port_cap, &byte_buffer.slice(0x10), &[]) .expect("Failed to reply w/ error") } } + + () } } diff --git a/rust/sys/denali/src/ahci/command.rs b/rust/sys/denali/src/ahci/command.rs index c827bb1..947082e 100644 --- a/rust/sys/denali/src/ahci/command.rs +++ b/rust/sys/denali/src/ahci/command.rs @@ -95,7 +95,7 @@ impl Command { command: SataCommand::DmaReadExt, lba, sector_cnt: lba_count, - paddr, + paddr: paddr, memory_region: None, } } diff --git a/rust/sys/denali/src/ahci/port_controller.rs b/rust/sys/denali/src/ahci/port_controller.rs index 42dfa00..556e8f7 100644 --- a/rust/sys/denali/src/ahci/port_controller.rs +++ b/rust/sys/denali/src/ahci/port_controller.rs @@ -44,8 +44,9 @@ impl PortController { }; // This leaves space for 8 prdt entries. - for (i, header) in command_list.iter_mut().enumerate() { - header.command_table_base_addr = (command_paddr + 0x500) + (0x100 * (i as u64)); + for i in 0..32 { + command_list[i].command_table_base_addr = + (command_paddr + 0x500) + (0x100 * (i as u64)); } let command_slots = array::from_fn(|_| Arc::new(Mutex::new(CommandStatus::Empty))); diff --git a/rust/sys/teton/src/framebuffer.rs b/rust/sys/teton/src/framebuffer.rs index f083367..dad4099 100644 --- a/rust/sys/teton/src/framebuffer.rs +++ b/rust/sys/teton/src/framebuffer.rs @@ -16,16 +16,15 @@ impl Framebuffer { }) } - fn draw_pixel(&mut self, row: u32, col: u32, pixel: u32) { + fn draw_pixel(&self, row: u32, col: u32, pixel: u32) { let index = row * (self.fb_info.pitch as u32 / 4) + col; self.memory_region.mut_slice()[index as usize] = pixel; } - pub fn draw_glyph(&mut self, glyph: &[u8], row: u32, col: u32) { + pub fn draw_glyph(&self, glyph: &[u8], row: u32, col: u32) { let gl_width = 8; let gl_height = 16; - #[allow(clippy::needless_range_loop)] for r in 0..gl_height { for c in 0..gl_width { if ((glyph[r] >> c) % 2) == 1 { diff --git a/rust/sys/teton/src/psf.rs b/rust/sys/teton/src/psf.rs index 3f99f65..f6a75a6 100644 --- a/rust/sys/teton/src/psf.rs +++ b/rust/sys/teton/src/psf.rs @@ -23,7 +23,7 @@ pub struct Psf { impl Psf { pub fn new(path: &str) -> Result { - let file = File::open(path)?; + let file = File::open(&path)?; let header = file.slice()[0..core::mem::size_of::()] .as_ptr() diff --git a/rust/sys/teton/src/terminal.rs b/rust/sys/teton/src/terminal.rs index 20b7ee0..2cd46ce 100644 --- a/rust/sys/teton/src/terminal.rs +++ b/rust/sys/teton/src/terminal.rs @@ -62,8 +62,10 @@ impl Terminal { } fn write_line(&mut self, line: &str) { - for (col, c) in line.chars().enumerate() { - self.console.write_char(c, self.row, col as u32); + let mut col = 0; + for c in line.chars() { + self.console.write_char(c, self.row, col); + col += 1; } self.row += 1 diff --git a/rust/sys/victoriafalls/src/lib.rs b/rust/sys/victoriafalls/src/lib.rs index a213a8b..b7b9ca3 100644 --- a/rust/sys/victoriafalls/src/lib.rs +++ b/rust/sys/victoriafalls/src/lib.rs @@ -12,8 +12,7 @@ static mut VFS_CLIENT: Option = None; fn get_client() -> &'static mut VFSClient { unsafe { - #[allow(static_mut_refs)] - if VFS_CLIENT.is_none() { + if let None = VFS_CLIENT { let endpoint_cap = yellowstone_yunq::from_init_endpoint() .get_endpoint(&yellowstone_yunq::GetEndpointRequest { endpoint_name: "victoriafalls".to_string(), @@ -22,7 +21,6 @@ fn get_client() -> &'static mut VFSClient { VFS_CLIENT = Some(VFSClient::new(Capability::take(endpoint_cap.endpoint))); } - #[allow(static_mut_refs)] VFS_CLIENT.as_mut().unwrap() } } diff --git a/rust/sys/victoriafalls/src/server.rs b/rust/sys/victoriafalls/src/server.rs index a901ea9..0c2edb8 100644 --- a/rust/sys/victoriafalls/src/server.rs +++ b/rust/sys/victoriafalls/src/server.rs @@ -35,7 +35,7 @@ impl VFSServerHandler for VictoriaFallsServerImpl { let mut inode_num = 2; // Start with root. - for path_token in tokens { + while let Some(path_token) = tokens.next() { inode_num = self.find_path_in_dir(inode_num, path_token)?; } @@ -57,7 +57,7 @@ impl VFSServerHandler for VictoriaFallsServerImpl { let mut inode_num = 2; // Start with root. - for path_token in tokens { + while let Some(path_token) = tokens.next() { inode_num = self.find_path_in_dir(inode_num, path_token)?; } diff --git a/rust/sys/voyageurs/src/xhci/data_structures/command_trb.rs b/rust/sys/voyageurs/src/xhci/data_structures/command_trb.rs deleted file mode 100644 index d55b85a..0000000 --- a/rust/sys/voyageurs/src/xhci/data_structures/command_trb.rs +++ /dev/null @@ -1,71 +0,0 @@ -use bitfield_struct::bitfield; - -use crate::xhci::data_structures::{TransferRequestBlock, TrbType}; - -pub struct EnableSlotTrb {} - -#[bitfield(u128)] -pub struct EnableSlotCommand { - __: u64, - __: u32, - #[bits(10)] - __: u16, - #[bits(6, default=TrbType::EnableSlotCommand)] - trb_type: TrbType, - #[bits(5)] - slot_type: u8, - #[bits(11)] - __: u16, -} - -impl From for CommandTrb { - fn from(value: EnableSlotCommand) -> Self { - Self(value.into_bits().into()) - } -} - -#[bitfield(u128)] -pub struct AddressDeviceCommand { - pub input_context_pointer: u64, - __: u32, - #[bits(9)] - __: u16, - pub block_set_address_request: bool, - #[bits(6, default=TrbType::AddressDeviceCommand)] - trb_typ: TrbType, - __: u8, - pub slot_id: u8, -} - -impl From for CommandTrb { - fn from(value: AddressDeviceCommand) -> Self { - Self(value.into_bits().into()) - } -} - -#[bitfield(u128)] -pub struct NoOpCommand { - __: u64, - __: u32, - cycle: bool, - #[bits(9)] - __: u16, - #[bits(6, default = TrbType::NoOpCommand)] - trb_type: TrbType, - __: u16, -} - -impl From for CommandTrb { - fn from(value: NoOpCommand) -> Self { - Self(value.into_bits().into()) - } -} - -/// Simple type to ensure we are only sending commands to command rings. -pub struct CommandTrb(TransferRequestBlock); - -impl From for TransferRequestBlock { - fn from(value: CommandTrb) -> Self { - value.0 - } -} diff --git a/rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs b/rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs index 4902da2..e4985d8 100644 --- a/rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs +++ b/rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs @@ -18,10 +18,10 @@ pub struct EventRingSegmentTableEntry { } impl EventRingSegmentTableEntry { - pub fn update_from_trb_ring(&mut self, trb_ring: &TrbRingSegment) { + pub fn from_trb_ring(&mut self, trb_ring: &TrbRingSegment) { mammoth::debug!("RSTE: {:0x}", self as *const _ as usize); self.ring_segment_base_address = trb_ring.physical_address() as u64; - assert!(self.ring_segment_base_address.is_multiple_of(64)); + assert!(self.ring_segment_base_address % 64 == 0); unsafe { core::ptr::write_volatile( &mut self.ring_segment_size as *mut u64, diff --git a/rust/sys/voyageurs/src/xhci/data_structures/event_trb.rs b/rust/sys/voyageurs/src/xhci/data_structures/event_trb.rs deleted file mode 100644 index 4754e7a..0000000 --- a/rust/sys/voyageurs/src/xhci/data_structures/event_trb.rs +++ /dev/null @@ -1,139 +0,0 @@ -use bitfield_struct::{bitenum, bitfield}; - -use crate::xhci::data_structures::{TransferRequestBlock, TrbType}; - -#[bitenum] -#[repr(u8)] -#[derive(Debug, Eq, PartialEq)] -pub enum CommandCompletionCode { - #[fallback] - #[allow(dead_code)] - Invalid = 0, - Success = 1, -} - -#[bitfield(u128)] -pub struct TransferEvent { - pub transfer_trb_pointer: u64, - - #[bits(24)] - pub trb_transfer_lenght: u32, - - /// Completion Code. This field encodes the completion status of the command that generated the - /// event. Refer to the respective command definition for a list of the possible Completion Codes - /// associated with the command. Refer to section 6.4.5 for an enumerated list of possible error - /// conditions. - #[bits(8)] - pub completion_code: CommandCompletionCode, - #[bits(10)] - __: u16, - /// TRB Type. This field identifies the type of the TRB. Refer to Table 6-91 for the definition of the - /// Command Completion Event TRB type ID - #[bits(6, default=TrbType::TransferEvent)] - pub trb_type: TrbType, - - #[bits(5)] - pub endpoint_id: u8, - #[bits(3)] - __: u8, - - pub slot_id: u8, -} - -#[bitfield(u128)] -pub struct CommandCompletionEvent { - /// Command TRB Pointer Hi and Lo. This field represents the high order bits of the 64-bit address - /// of the Command TRB that generated this event. Note that this field is not valid for some - /// Completion Code values. Refer to Table 6-90 for specific cases. - /// - /// The memory structure referenced by this physical memory pointer shall be aligned on a 16-byte - /// address boundary. - pub command_trb_pointer: u64, - /// Command Completion Parameter. This field may optionally be set by a command. Refer to - /// section 4.6.6.1 for specific usage. If a command does not utilize this field it shall be treated as - /// RsvdZ. - #[bits(24)] - pub command_completion_parameter: u64, - /// Completion Code. This field encodes the completion status of the command that generated the - /// event. Refer to the respective command definition for a list of the possible Completion Codes - /// associated with the command. Refer to section 6.4.5 for an enumerated list of possible error - /// conditions. - #[bits(8)] - pub completion_code: CommandCompletionCode, - /// Cycle bit (C). This bit is used to mark the Dequeue Pointer of an Event Ring - pub cycle_bit: bool, - #[bits(9)] - __: u16, - /// TRB Type. This field identifies the type of the TRB. Refer to Table 6-91 for the definition of the - /// Command Completion Event TRB type ID - #[bits(6, default=TrbType::CommandCompletionEvent)] - pub trb_type: TrbType, - /// VF ID. The ID of the Virtual Function that generated the event. Note that this field is valid only if - /// Virtual Functions are enabled. If they are not enabled this field shall be cleared to ‘0’. - pub vf_id: u8, - /// Slot ID. The Slot ID field shall be updated by the xHC to reflect the slot associated with the - /// command that generated the event, with the following exceptions: - /// - /// - The Slot ID shall be cleared to ‘0’ for No Op, Set Latency Tolerance Value, Get Port Bandwidth, - /// and Force Event Commands. - /// - /// - The Slot ID shall be set to the ID of the newly allocated Device Slot for the Enable Slot - /// Command. - /// - /// - The value of Slot ID shall be vendor defined when generated by a vendor defined command. - /// - /// This value is used as an index in the Device Context Base Address Array to select the Device - /// Context of the source device. If this Event is due to a Host Controller Command, then this field - /// shall be cleared to ‘0’. - pub slot_id: u8, -} - -#[bitfield(u128)] -pub struct PortStatusChangeEvent { - #[bits(24)] - __: u32, - pub port_id: u8, - __: u32, - #[bits(24)] - __: u32, - #[bits(8)] - pub completion_code: CommandCompletionCode, - #[bits(10)] - __: u16, - #[bits(6, default=TrbType::PortStatusChangeEvent)] - trb_type: TrbType, - __: u16, -} - -pub enum EventTrb { - Transfer(TransferEvent), - CommandCompletion(CommandCompletionEvent), - PortStatusChange(PortStatusChangeEvent), - BandwidthRequest(TransferRequestBlock), - Doorbell(TransferRequestBlock), - HostController(TransferRequestBlock), - DeviceNotification(TransferRequestBlock), - MFINDEXWrap(TransferRequestBlock), -} - -impl From for EventTrb { - fn from(value: TransferRequestBlock) -> Self { - match value.trb_type() { - TrbType::TransferEvent => { - EventTrb::Transfer(TransferEvent::from_bits(value.into_bits())) - } - TrbType::CommandCompletionEvent => { - EventTrb::CommandCompletion(CommandCompletionEvent::from_bits(value.into_bits())) - } - TrbType::PortStatusChangeEvent => { - EventTrb::PortStatusChange(PortStatusChangeEvent::from_bits(value.into_bits())) - } - TrbType::BandwidthRequestEvent => EventTrb::BandwidthRequest(value), - TrbType::DoorbellEvent => EventTrb::Doorbell(value), - TrbType::HostControllerEvent => EventTrb::HostController(value), - TrbType::DeviceNotificationEvent => EventTrb::DeviceNotification(value), - TrbType::MFINDEXWrapEvent => EventTrb::MFINDEXWrap(value), - t => panic!("Unknown trb type on event ring: {:?}", t), - } - } -} diff --git a/rust/sys/voyageurs/src/xhci/data_structures/mod.rs b/rust/sys/voyageurs/src/xhci/data_structures/mod.rs index 5069bf6..6b33f73 100644 --- a/rust/sys/voyageurs/src/xhci/data_structures/mod.rs +++ b/rust/sys/voyageurs/src/xhci/data_structures/mod.rs @@ -1,18 +1,14 @@ -mod command_trb; mod device_context; mod endpoint_context; mod event_ring_segment_table; -mod event_trb; mod input_context; mod slot_context; mod trb; mod trb_ring_segment; -pub use command_trb::*; pub use device_context::*; pub use endpoint_context::*; pub use event_ring_segment_table::*; -pub use event_trb::*; pub use input_context::*; pub use slot_context::*; pub use trb::*; diff --git a/rust/sys/voyageurs/src/xhci/data_structures/trb.rs b/rust/sys/voyageurs/src/xhci/data_structures/trb.rs index 7cb0338..e84afe7 100644 --- a/rust/sys/voyageurs/src/xhci/data_structures/trb.rs +++ b/rust/sys/voyageurs/src/xhci/data_structures/trb.rs @@ -75,6 +75,29 @@ where } } +#[bitfield(u128)] +pub struct TrbNoOp { + __: u64, + #[bits(22)] + __: u32, + #[bits(10, default = 0)] + interrupter_target: u16, + cycle: bool, + evaluate_next: bool, + __: bool, + __: bool, + chain: bool, + #[bits(default = true)] + interrupt_on_completion: bool, + #[bits(4)] + __: u8, + #[bits(6, default = TrbType::NoOpCommand)] + trb_type: TrbType, + __: u16, +} + +impl TypedTrb for TrbNoOp {} + #[bitfield(u128)] pub struct TrbLink { /// Ring Segment Pointer Hi and Lo. These fields represent the high order bits of the 64-bit base @@ -118,3 +141,138 @@ pub struct TrbLink { } impl TypedTrb for TrbLink {} + +#[bitfield(u128)] +pub struct TrbTransferEvent { + pub transfer_trb_pointer: u64, + + #[bits(24)] + pub trb_transfer_lenght: u32, + + /// Completion Code. This field encodes the completion status of the command that generated the + /// event. Refer to the respective command definition for a list of the possible Completion Codes + /// associated with the command. Refer to section 6.4.5 for an enumerated list of possible error + /// conditions. + pub completion_code: u8, + #[bits(10)] + __: u16, + /// TRB Type. This field identifies the type of the TRB. Refer to Table 6-91 for the definition of the + /// Command Completion Event TRB type ID + #[bits(6, default=TrbType::TransferEvent)] + pub trb_type: TrbType, + + #[bits(5)] + pub endpoint_id: u8, + #[bits(3)] + __: u8, + + pub slot_id: u8, +} + +impl TypedTrb for TrbTransferEvent {} + +#[bitenum] +#[repr(u8)] +pub enum CommandCompletionCode { + #[fallback] + Invalid = 0, + Success = 1, +} + +#[bitfield(u128)] +pub struct TrbCommandCompletion { + /// Command TRB Pointer Hi and Lo. This field represents the high order bits of the 64-bit address + /// of the Command TRB that generated this event. Note that this field is not valid for some + /// Completion Code values. Refer to Table 6-90 for specific cases. + /// + /// The memory structure referenced by this physical memory pointer shall be aligned on a 16-byte + /// address boundary. + pub command_trb_pointer: u64, + /// Command Completion Parameter. This field may optionally be set by a command. Refer to + /// section 4.6.6.1 for specific usage. If a command does not utilize this field it shall be treated as + /// RsvdZ. + #[bits(24)] + pub command_completion_parameter: u64, + /// Completion Code. This field encodes the completion status of the command that generated the + /// event. Refer to the respective command definition for a list of the possible Completion Codes + /// associated with the command. Refer to section 6.4.5 for an enumerated list of possible error + /// conditions. + pub completion_code: u8, + /// Cycle bit (C). This bit is used to mark the Dequeue Pointer of an Event Ring + pub cycle_bit: bool, + #[bits(9)] + __: u16, + /// TRB Type. This field identifies the type of the TRB. Refer to Table 6-91 for the definition of the + /// Command Completion Event TRB type ID + #[bits(6, default=TrbType::CommandCompletionEvent)] + pub trb_type: TrbType, + /// VF ID. The ID of the Virtual Function that generated the event. Note that this field is valid only if + /// Virtual Functions are enabled. If they are not enabled this field shall be cleared to ‘0’. + pub vf_id: u8, + /// Slot ID. The Slot ID field shall be updated by the xHC to reflect the slot associated with the + /// command that generated the event, with the following exceptions: + /// + /// - The Slot ID shall be cleared to ‘0’ for No Op, Set Latency Tolerance Value, Get Port Bandwidth, + /// and Force Event Commands. + /// + /// - The Slot ID shall be set to the ID of the newly allocated Device Slot for the Enable Slot + /// Command. + /// + /// - The value of Slot ID shall be vendor defined when generated by a vendor defined command. + /// + /// This value is used as an index in the Device Context Base Address Array to select the Device + /// Context of the source device. If this Event is due to a Host Controller Command, then this field + /// shall be cleared to ‘0’. + pub slot_id: u8, +} + +impl TypedTrb for TrbCommandCompletion {} + +#[bitfield(u128)] +pub struct TrbPortStatusChangeEvent { + #[bits(24)] + __: u32, + pub port_id: u8, + __: u32, + #[bits(24)] + __: u32, + pub completion_code: u8, + #[bits(10)] + __: u16, + #[bits(6, default=TrbType::PortStatusChangeEvent)] + trb_type: TrbType, + __: u16, +} + +impl TypedTrb for TrbPortStatusChangeEvent {} + +#[bitfield(u128)] +pub struct TrbEnableSlotCommand { + __: u64, + __: u32, + #[bits(10)] + __: u16, + #[bits(6, default=TrbType::EnableSlotCommand)] + trb_type: TrbType, + #[bits(5)] + slot_type: u8, + #[bits(11)] + __: u16, +} + +impl TypedTrb for TrbEnableSlotCommand {} + +#[bitfield(u128)] +pub struct TrbAddressDeviceCommand { + pub input_context_pointer: u64, + __: u32, + #[bits(9)] + __: u16, + pub block_set_address_request: bool, + #[bits(6, default=TrbType::AddressDeviceCommand)] + trb_typ: TrbType, + __: u8, + pub slot_id: u8, +} + +impl TypedTrb for TrbAddressDeviceCommand {} diff --git a/rust/sys/voyageurs/src/xhci/device_context_base_array.rs b/rust/sys/voyageurs/src/xhci/device_context_base_array.rs index d69497c..6c32179 100644 --- a/rust/sys/voyageurs/src/xhci/device_context_base_array.rs +++ b/rust/sys/voyageurs/src/xhci/device_context_base_array.rs @@ -4,7 +4,7 @@ use mammoth::physical_box::PhysicalBox; use crate::xhci::{ data_structures::{ DeviceContext, EndpointContextFields, EndpointState, EndpointType, InputContext, - TRDequeuePointer, TransferEvent, + TRDequeuePointer, TrbTransferEvent, }, registers::DoorbellPointer, trb_ring::TrbRing, @@ -20,27 +20,22 @@ impl DeviceContextBaseArray { pub struct DeviceSlot { device_context: PhysicalBox, - endpoint_0_transfer_ring: TrbRing, - doorbell: DoorbellPointer, + endpoint_0_transfer_ring: TrbRing, } impl DeviceSlot { - fn new(doorbell: DoorbellPointer) -> Self { + fn new() -> Self { Self { device_context: PhysicalBox::new(DeviceContext::default()), endpoint_0_transfer_ring: TrbRing::new(), - doorbell, } } - pub fn send_control_command(&mut self) { - self.doorbell.ring(1); - } } pub struct DeviceSlotManager { device_context_base_array: DeviceContextBaseArray, slots: Box<[Option]>, - doorbells: Box<[Option]>, + doorbells: Box<[DoorbellPointer]>, } impl DeviceSlotManager { @@ -54,7 +49,7 @@ impl DeviceSlotManager { slots: core::iter::repeat_with(|| None) .take(max_slots as usize) .collect(), - doorbells: doorbells.into_iter().map(|d| Some(d)).collect(), + doorbells, } } @@ -71,11 +66,7 @@ impl DeviceSlotManager { port_number: u8, ) -> PhysicalBox { // TODO: Ensure alignment - let device_slot = DeviceSlot::new( - self.doorbells[(slot_id - 1) as usize] - .take() - .expect("Slot already allocated."), - ); + let device_slot = DeviceSlot::new(); let mut input_context = PhysicalBox::new(InputContext::default()); // The Add Context flags for the Slot Context and the Endpoint 0 Context shall be set to ‘1’. diff --git a/rust/sys/voyageurs/src/xhci/driver.rs b/rust/sys/voyageurs/src/xhci/driver.rs index 1a0fc0e..6f69b63 100644 --- a/rust/sys/voyageurs/src/xhci/driver.rs +++ b/rust/sys/voyageurs/src/xhci/driver.rs @@ -1,17 +1,20 @@ +use alloc::boxed::Box; use alloc::sync::Arc; +use mammoth::cap::Capability; use mammoth::sync::Mutex; use mammoth::task::Spawner; use mammoth::task::Task; use super::registers::{self}; -use crate::xhci::data_structures::AddressDeviceCommand; use crate::xhci::data_structures::CommandCompletionCode; -use crate::xhci::data_structures::CommandCompletionEvent; -use crate::xhci::data_structures::CommandTrb; -use crate::xhci::data_structures::EnableSlotCommand; -use crate::xhci::data_structures::EventTrb; -use crate::xhci::data_structures::NoOpCommand; -use crate::xhci::data_structures::PortStatusChangeEvent; +use crate::xhci::data_structures::TransferRequestBlock; +use crate::xhci::data_structures::TrbAddressDeviceCommand; +use crate::xhci::data_structures::TrbCommandCompletion; +use crate::xhci::data_structures::TrbEnableSlotCommand; +use crate::xhci::data_structures::TrbNoOp; +use crate::xhci::data_structures::TrbPortStatusChangeEvent; +use crate::xhci::data_structures::TrbType; +use crate::xhci::data_structures::TypedTrb; use crate::xhci::device_context_base_array::DeviceSlotManager; use crate::xhci::interrupter::Interrupter; use crate::xhci::registers::DoorbellPointer; @@ -37,7 +40,7 @@ impl XHCIDriver { ((pci_device.header().bars[1] as usize) << 32) | (pci_device.header().bars[0] as usize); let irq_port_cap = pci_device.register_msi().unwrap(); - let (operational, capabilities) = HostControllerOperationalWrapper::new(address); + let (operational, capabilities) = HostControllerOperationalWrapper::new(address as usize); let max_slots = capabilities.params_1.max_device_slots(); let doorbell_physical = address + capabilities.doorbell_offset as usize; @@ -150,49 +153,38 @@ impl XHCIDriver { } pub fn interrupt_loop(self: Arc, spawner: Spawner) { - let completion_handler = |trb| { + let completion_handler = |trb: TransferRequestBlock| { self.clone().handle_completion(spawner.clone(), trb); }; self.interrupter.lock().interrupt_loop(completion_handler); } - fn handle_completion(self: Arc, spawner: Spawner, trb: EventTrb) { - match trb { - EventTrb::Transfer(trb) => { - mammoth::debug!("Unhandled transfer event: {:?}", trb); + fn handle_completion(self: Arc, spawner: Spawner, trb: TransferRequestBlock) { + match trb.trb_type() { + TrbType::TransferEvent => { + todo!("Handle Transfer") } - EventTrb::CommandCompletion(trb) => { + TrbType::CommandCompletionEvent => { self.command_ring .lock() .trb_ring - .handle_completion(trb, trb.command_trb_pointer() as usize); + .handle_completion(TrbCommandCompletion::from_trb(trb)); } - EventTrb::PortStatusChange(trb) => { + TrbType::PortStatusChangeEvent => { + let trb = TrbPortStatusChangeEvent::from_trb(trb); let self_clone = self.clone(); spawner.spawn(Task::new(async move { self_clone.port_status_change(trb).await })); } - EventTrb::BandwidthRequest(trb) => { - mammoth::debug!("Unhandled bandwidth request event: {:?}", trb); - } - EventTrb::Doorbell(trb) => { - mammoth::debug!("Unhandled doorbell event: {:?}", trb); - } - EventTrb::HostController(trb) => { - mammoth::debug!("Unhandled host controller event: {:?}", trb); - } - EventTrb::DeviceNotification(trb) => { - mammoth::debug!("Unhandled device notification event: {:?}", trb); - } - EventTrb::MFINDEXWrap(trb) => { - mammoth::debug!("Unhandled MFINDEX wrap event: {:?}", trb); + _ => { + panic!("Unhandled event type: {:?}", trb.trb_type()); } } } - async fn send_command(&self, trb: CommandTrb) -> CommandCompletionEvent { + async fn send_command(&self, trb: impl TypedTrb) -> TrbCommandCompletion { // Split the future and the await so the lock is dropped before we await. let future = { self.command_ring.lock().enqueue_command(trb) }; future.await @@ -202,9 +194,9 @@ impl XHCIDriver { #[cfg(feature = "debug")] mammoth::debug!("Sending no op command."); - let result = self.send_command(NoOpCommand::new().into()).await; + let result = self.send_command(TrbNoOp::new()).await; - assert_eq!(result.completion_code(), CommandCompletionCode::Success); + assert!(result.completion_code() == CommandCompletionCode::Success.into_bits()); #[cfg(feature = "debug")] mammoth::debug!("Successfully tested no op command."); @@ -229,12 +221,15 @@ impl XHCIDriver { } } - async fn port_status_change(self: Arc, status_change: PortStatusChangeEvent) { + async fn port_status_change(self: Arc, status_change: TrbPortStatusChangeEvent) { // Ports are indexed from 1. let port_id = status_change.port_id(); let port_index = (port_id - 1) as usize; - let port_status = self.operational.get_port(port_index).status_and_control; + let port_status = self + .operational + .get_port(port_index as usize) + .status_and_control; #[cfg(feature = "debug")] mammoth::debug!("Port status change for port {}", port_id); @@ -253,8 +248,8 @@ impl XHCIDriver { #[cfg(feature = "debug")] mammoth::debug!("Enabling slot."); - let resp = self.send_command(EnableSlotCommand::new().into()).await; - assert_eq!(resp.completion_code(), CommandCompletionCode::Success); + let resp = self.send_command(TrbEnableSlotCommand::new()).await; + assert!(resp.completion_code() == CommandCompletionCode::Success.into_bits()); let slot = resp.slot_id(); @@ -271,12 +266,11 @@ impl XHCIDriver { let resp = self .send_command( - AddressDeviceCommand::new() + TrbAddressDeviceCommand::new() .with_slot_id(slot) - .with_input_context_pointer(input_context.physical_address() as u64) - .into(), + .with_input_context_pointer(input_context.physical_address() as u64), ) .await; - assert_eq!(resp.completion_code(), CommandCompletionCode::Success); + assert!(resp.completion_code() == CommandCompletionCode::Success.into_bits()); } } diff --git a/rust/sys/voyageurs/src/xhci/event_ring.rs b/rust/sys/voyageurs/src/xhci/event_ring.rs index 116f27e..58e5d75 100644 --- a/rust/sys/voyageurs/src/xhci/event_ring.rs +++ b/rust/sys/voyageurs/src/xhci/event_ring.rs @@ -1,7 +1,7 @@ use alloc::vec::Vec; use crate::xhci::{ - data_structures::{EventRingSegmentTable, EventTrb, TransferRequestBlock, TrbRingSegment}, + data_structures::{EventRingSegmentTable, TransferRequestBlock, TrbRingSegment}, trb_ring::TrbPointer, }; @@ -24,7 +24,7 @@ impl EventRing { trb_pointer: TrbPointer::default(), }; - event_ring.segment_table[0].update_from_trb_ring(&event_ring.segments[0]); + event_ring.segment_table[0].from_trb_ring(&event_ring.segments[0]); event_ring } @@ -58,13 +58,13 @@ impl EventRing { } } - pub fn get_next(&mut self) -> Option { + pub fn get_next(&mut self) -> Option { let curr = self.current_trb(); if curr.cycle() != self.cycle_bit { None } else { self.increment_pointer(); - Some(curr.into()) + Some(curr) } } } diff --git a/rust/sys/voyageurs/src/xhci/interrupter.rs b/rust/sys/voyageurs/src/xhci/interrupter.rs index 05fca51..483dc54 100644 --- a/rust/sys/voyageurs/src/xhci/interrupter.rs +++ b/rust/sys/voyageurs/src/xhci/interrupter.rs @@ -1,9 +1,10 @@ use core::ptr::NonNull; +use alloc::boxed::Box; use mammoth::cap::Capability; use crate::xhci::{ - data_structures::{EventTrb, TransferRequestBlock}, + data_structures::TransferRequestBlock, event_ring::EventRing, registers::{InterrupterModeration, InterrupterRegisterSet, InterrupterRegisters}, }; @@ -47,14 +48,17 @@ impl Interrupter { self.register_set.enable_interrupts(); } - pub fn interrupt_loop(&mut self, completion_handler: impl Fn(EventTrb)) { + pub fn interrupt_loop(&mut self, completion_handler: impl Fn(TransferRequestBlock) -> ()) { loop { let _ = mammoth::syscall::port_recv(&self.irq_port_cap, &mut [], &mut []).unwrap(); + #[cfg(feature = "debug")] + mammoth::debug!("Received Interrupt."); + while let Some(trb) = self.event_ring.get_next() { completion_handler(trb); + self.register_set + .update_dequeue_pointer_clearing_busy(self.event_ring.erdp_physical_address()); } - self.register_set - .update_dequeue_pointer_clearing_busy(self.event_ring.erdp_physical_address()); } } } diff --git a/rust/sys/voyageurs/src/xhci/registers/doorbell.rs b/rust/sys/voyageurs/src/xhci/registers/doorbell.rs index 9427efe..0ffbe80 100644 --- a/rust/sys/voyageurs/src/xhci/registers/doorbell.rs +++ b/rust/sys/voyageurs/src/xhci/registers/doorbell.rs @@ -1,6 +1,6 @@ use core::ptr::NonNull; -use alloc::boxed::Box; +use alloc::{boxed::Box, vec::Vec}; use bitfield_struct::bitfield; use volatile::VolatileRef; diff --git a/rust/sys/voyageurs/src/xhci/registers/host_controller.rs b/rust/sys/voyageurs/src/xhci/registers/host_controller.rs index 34037d6..6d32703 100644 --- a/rust/sys/voyageurs/src/xhci/registers/host_controller.rs +++ b/rust/sys/voyageurs/src/xhci/registers/host_controller.rs @@ -341,7 +341,7 @@ pub struct UsbConfigure { /// XHCI Spec Section 5.4 /// -/// The base address of this register space is referred to as Operational Base. The +/// > The base address of this register space is referred to as Operational Base. The /// Operational Base shall be Dword aligned and is calculated by adding the value /// of the Capability Registers Length (CAPLENGTH) register (refer to Section 5.3.1) /// to the Capability Base address. All registers are multiples of 32 bits in length diff --git a/rust/sys/voyageurs/src/xhci/trb_ring.rs b/rust/sys/voyageurs/src/xhci/trb_ring.rs index 34cdb47..e5789da 100644 --- a/rust/sys/voyageurs/src/xhci/trb_ring.rs +++ b/rust/sys/voyageurs/src/xhci/trb_ring.rs @@ -5,7 +5,7 @@ use mammoth::sync::Mutex; use crate::xhci::{ data_structures::{ - CommandCompletionEvent, CommandTrb, TransferRequestBlock, TrbLink, TrbRingSegment, TypedTrb, + TransferRequestBlock, TrbCommandCompletion, TrbLink, TrbRingSegment, TypedTrb, }, registers::DoorbellPointer, }; @@ -20,11 +20,11 @@ struct TrbFutureState { } #[derive(Clone)] -pub struct TrbFuture { +pub struct TrbFuture { state: Arc>>, } -impl TrbFuture { +impl TrbFuture { fn new(paddr: usize) -> Self { Self { state: Arc::new(Mutex::new(TrbFutureState { @@ -36,7 +36,7 @@ impl TrbFuture { } } -impl Future for TrbFuture { +impl Future for TrbFuture { type Output = T; fn poll( @@ -70,14 +70,14 @@ impl TrbPointer { } } -pub struct TrbRing { +pub struct TrbRing { segments: Vec, enqueue_pointer: TrbPointer, cycle_bit: bool, pending_futures: VecDeque>, } -impl TrbRing { +impl TrbRing { pub fn new() -> Self { Self { // TODO: What size and count should this be. @@ -147,15 +147,17 @@ impl TrbRing { } } - pub fn handle_completion(&mut self, completion_trb: T, physical_address: usize) { + pub fn handle_completion(&mut self, completion_trb: T) { + let trb = completion_trb.to_trb(); + let paddr = trb.parameter() as usize; let completion = self.pending_futures.pop_front().unwrap(); let mut completion = completion.state.lock(); // TODO: Handle recovery scenarios here. assert!( - completion.physical_address == physical_address, + completion.physical_address == paddr, "Got an unexpected command completion. Expected: {:0x}, Got: {:0x}", completion.physical_address, - physical_address + paddr ); completion.response = Some(completion_trb); @@ -166,7 +168,7 @@ impl TrbRing { } pub struct CommandRing { - pub trb_ring: TrbRing, + pub trb_ring: TrbRing, doorbell: DoorbellPointer, } @@ -179,8 +181,8 @@ impl CommandRing { } // We have to explicitly return a future her - pub fn enqueue_command(&mut self, command: CommandTrb) -> TrbFuture { - let fut = self.trb_ring.enqueue_trb(command.into()); + pub fn enqueue_command(&mut self, command: impl TypedTrb) -> TrbFuture { + let fut = self.trb_ring.enqueue_trb(command.to_trb()); // Command Doorbell is always 0. self.doorbell.ring(0); fut diff --git a/rust/sys/yellowstone/src/server.rs b/rust/sys/yellowstone/src/server.rs index a6d5fa1..8cc4a4b 100644 --- a/rust/sys/yellowstone/src/server.rs +++ b/rust/sys/yellowstone/src/server.rs @@ -57,8 +57,9 @@ impl YellowstoneServerContext { pub fn wait(&self, service: &str) -> Result<(), ZError> { loop { - if self.service_map.lock().get(service).is_some() { - return Ok(()); + match self.service_map.lock().get(service) { + Some(_) => return Ok(()), + None => {} } self.registration_semaphore.wait().unwrap(); } diff --git a/scripts/build.sh b/scripts/build.sh index 9b64905..5cee593 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -19,11 +19,11 @@ CARGO_SYS_ROOT="${DIR}/../sysroot/" pushd "${DIR}/../rust" for BIN in ${DIR}/../rust/usr/*/; do - cargo install --force --path "${BIN}" --root $CARGO_USR_ROOT + cargo install --offline --force --path "${BIN}" --root $CARGO_USR_ROOT done for BIN in ${DIR}/../rust/sys/*/; do - cargo install --all-features --force --path "${BIN}" --root $CARGO_SYS_ROOT + cargo install --offline --all-features --force --path "${BIN}" --root $CARGO_SYS_ROOT done popd diff --git a/yunq/rust/src/codegen.rs b/yunq/rust/src/codegen.rs index 9462f4b..7eefb66 100644 --- a/yunq/rust/src/codegen.rs +++ b/yunq/rust/src/codegen.rs @@ -122,7 +122,7 @@ fn parse_field(field: &Field) -> TokenStream { let rep_offset = buf.at::(yunq::message::field_offset(offset, #ind))?; let rep_len = buf.at::(yunq::message::field_offset(offset, #ind) + 4)?; - yunq::message::parse_repeated_message(buf, offset + rep_offset as usize, rep_len as usize, caps)? + yunq::message::parse_repeated_message(buf, offset + rep_offset as usize, rep_len as usize, &caps)? }; }, } @@ -174,7 +174,7 @@ fn generate_serialize(message: &Message) -> TokenStream { &self, buf: &mut yunq::ByteBuffer, offset: usize, - caps: &mut Vec, + caps: &mut alloc::vec::Vec, ) -> Result { let num_fields = #num_fields; let core_size: u32 = (yunq::message::MESSAGE_HEADER_SIZE + 8 * num_fields) as u32; @@ -183,10 +183,10 @@ fn generate_serialize(message: &Message) -> TokenStream { #(#serializers)* - buf.write_at(offset, yunq::message::MESSAGE_IDENT)?; + buf.write_at(offset + 0, yunq::message::MESSAGE_IDENT)?; buf.write_at(offset + 4, core_size)?; buf.write_at(offset + 8, next_extension)?; - buf.write_at(offset + 12, 0_u32)?; + buf.write_at(offset + 12, 0 as u32)?; Ok(next_extension as usize) } } @@ -200,12 +200,12 @@ fn generate_parse(message: &Message) -> TokenStream { fn parse( buf: &yunq::ByteBuffer, offset: usize, - caps: &[z_cap_t], + caps: &alloc::vec::Vec, ) -> Result where Self: Sized, { - if buf.at::(offset)? != yunq::message::MESSAGE_IDENT { + if buf.at::(offset + 0)? != yunq::message::MESSAGE_IDENT { mammoth::debug!("Expected IDENT at offest {:#x}, got {:#x}", offset, buf.at::(offset)?); return Err(ZError::INVALID_ARGUMENT); } @@ -303,7 +303,7 @@ fn generate_server_case(method: &Method) -> TokenStream { #id => { let req = #req::parse_from_request(byte_buffer, cap_buffer)?; let resp = self.handler.#name(req)?; - cap_buffer.clear(); + cap_buffer.resize(0, 0); let resp_len = resp.serialize_as_request(0, byte_buffer, cap_buffer)?; Ok(resp_len) }, @@ -312,7 +312,7 @@ fn generate_server_case(method: &Method) -> TokenStream { #id => { let req = #req::parse_from_request(byte_buffer, cap_buffer)?; self.handler.#name(req)?; - cap_buffer.clear(); + cap_buffer.resize(0, 0); // TODO: Implement serialization for EmptyMessage so this is less hacky. yunq::message::serialize_error(byte_buffer, ZError::from(0)); Ok(0x10) @@ -321,7 +321,7 @@ fn generate_server_case(method: &Method) -> TokenStream { (None, Some(_)) => quote! { #id => { let resp = self.handler.#name()?; - cap_buffer.clear(); + cap_buffer.resize(0, 0); let resp_len = resp.serialize_as_request(0, byte_buffer, cap_buffer)?; Ok(resp_len) }, @@ -403,7 +403,7 @@ fn generate_async_server_case(method: &Method) -> TokenStream { #id => { let req = #req::parse_from_request(byte_buffer, cap_buffer)?; let resp = self.handler.#name(req).await?; - cap_buffer.clear(); + cap_buffer.resize(0, 0); let resp_len = resp.serialize_as_request(0, byte_buffer, cap_buffer)?; Ok(resp_len) }, @@ -412,7 +412,7 @@ fn generate_async_server_case(method: &Method) -> TokenStream { #id => { let req = #req::parse_from_request(byte_buffer, cap_buffer)?; self.handler.#name(req).await?; - cap_buffer.clear(); + cap_buffer.resize(0, 0); // TODO: Implement serialization for EmptyMessage so this is less hacky. yunq::message::serialize_error(byte_buffer, ZError::from(0)); Ok(0x10) @@ -421,7 +421,7 @@ fn generate_async_server_case(method: &Method) -> TokenStream { (None, Some(_)) => quote! { #id => { let resp = self.handler.#name().await?; - cap_buffer.clear(); + cap_buffer.resize(0, 0); let resp_len = resp.serialize_as_request(0, byte_buffer, cap_buffer)?; Ok(resp_len) }, @@ -547,7 +547,6 @@ pub fn generate_code(ast: &[Decl]) -> String { use alloc::vec::Vec; use mammoth::zion::z_cap_t; use mammoth::zion::ZError; - #[allow(unused_imports)] use yunq::ByteBuffer; use yunq::YunqMessage;