Compare commits
7 commits
c1ab41bbad
...
592b5b468f
| Author | SHA1 | Date | |
|---|---|---|---|
| 592b5b468f | |||
| 8b022a6b24 | |||
| d5d7e2c7ab | |||
| 22b43de6dc | |||
| b9cd550a63 | |||
| 1a48911745 | |||
| 311755c812 |
44 changed files with 486 additions and 347 deletions
42
.forgejo/workflows/ci.yml
Normal file
42
.forgejo/workflows/ci.yml
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
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
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2025-10-02"
|
||||
components = ["rustfmt", "rust-analyzer"]
|
||||
components = ["rustfmt", "rust-analyzer", "clippy", "rust-src"]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use mammoth::thread;
|
|||
#[allow(dead_code)]
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
|
||||
enum Keycode {
|
||||
UnknownKeycode = 0x0,
|
||||
Unknown = 0x0,
|
||||
|
||||
A = 0x1,
|
||||
B = 0x2,
|
||||
|
|
@ -135,7 +135,7 @@ impl Keycode {
|
|||
0x37 => Keycode::Period,
|
||||
0x38 => Keycode::FSlash,
|
||||
0x39 => Keycode::Esc,
|
||||
_ => Keycode::UnknownKeycode,
|
||||
_ => Keycode::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 let None = self.inode_table_map[block_group_num] {
|
||||
if self.inode_table_map[block_group_num].is_none() {
|
||||
debug!(
|
||||
"Cache MISS on inode table for block_group {}",
|
||||
block_group_num
|
||||
|
|
@ -148,17 +148,15 @@ 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();
|
||||
let dbl_indr_blocks: &[u32] = &dbl_indr_block_mem.slice()[0..num_dbl_indr];
|
||||
|
||||
let mut blocks_to_read = Vec::new();
|
||||
|
||||
for i in 0..num_dbl_indr {
|
||||
for (i, dbl_indr_block) in dbl_indr_blocks.iter().enumerate() {
|
||||
let num_blocks_in_single = min(num_blocks - (256 * i), 256);
|
||||
blocks_to_read.append(
|
||||
&mut self.get_blocks_from_single_indirect(
|
||||
dbl_indr_blocks[i] as u64,
|
||||
num_blocks_in_single,
|
||||
),
|
||||
&mut self
|
||||
.get_blocks_from_single_indirect(*dbl_indr_block as u64, num_blocks_in_single),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -176,7 +174,7 @@ impl Ext2Driver {
|
|||
|
||||
let mut blocks = Vec::new();
|
||||
|
||||
while let Some(block) = iter.next() {
|
||||
for block in iter {
|
||||
if block as u64 == (curr_block.lba + curr_block.size) {
|
||||
curr_block.size += 1;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,9 @@ pub struct Inode {
|
|||
|
||||
const _: () = assert!(size_of::<Inode>() == 128);
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const EXT2_FT_FILE: u8 = 0x1;
|
||||
#[allow(dead_code)]
|
||||
pub const EXT2_FT_DIR: u8 = 0x2;
|
||||
|
||||
#[repr(C, packed)]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ use core::ffi::c_void;
|
|||
|
||||
use crate::zion::{self, z_cap_t, ZError};
|
||||
|
||||
#[must_use]
|
||||
fn syscall<T>(id: u64, req: &T) -> Result<(), ZError> {
|
||||
unsafe {
|
||||
let resp = zion::SysCall1(id, req as *const T as *const c_void);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use crate::cap::Capability;
|
||||
use crate::debug;
|
||||
use crate::init;
|
||||
use crate::syscall;
|
||||
use crate::zion::ZError;
|
||||
|
|
@ -237,7 +236,7 @@ fn load_program_segment(
|
|||
let page_offset = prog_header.vaddr & 0xFFF;
|
||||
let mem_size = page_offset + prog_header.mem_size;
|
||||
|
||||
let mem_object = crate::mem::MemoryRegion::new(mem_size)?;
|
||||
let mut mem_object = crate::mem::MemoryRegion::new(mem_size)?;
|
||||
|
||||
mem_object.zero_region();
|
||||
|
||||
|
|
|
|||
|
|
@ -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 let Err(_) = resp {
|
||||
if resp.is_err() {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,21 +2,20 @@ use alloc::string::String;
|
|||
use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Writer {
|
||||
int_vec: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Writer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
int_vec: Vec::new(),
|
||||
}
|
||||
Writer::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for Writer {
|
||||
fn into(self) -> String {
|
||||
String::from_utf8(self.int_vec).expect("Failed to convert")
|
||||
impl From<Writer> for String {
|
||||
fn from(value: Writer) -> Self {
|
||||
String::from_utf8(value.int_vec).expect("Failed to convert")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ 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")]
|
||||
|
|
@ -91,7 +90,7 @@ impl MemoryRegion {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn mut_slice<T>(&self) -> &mut [T] {
|
||||
pub fn mut_slice<T>(&mut self) -> &mut [T] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
self.virt_addr as *mut T,
|
||||
|
|
@ -100,7 +99,7 @@ impl MemoryRegion {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn zero_region(&self) {
|
||||
pub fn zero_region(&mut self) {
|
||||
for i in self.mut_slice() {
|
||||
*i = 0;
|
||||
}
|
||||
|
|
@ -118,7 +117,8 @@ impl MemoryRegion {
|
|||
|
||||
/// Creates a reference from a given offset.
|
||||
///
|
||||
/// SAFETY: Caller must ensure that the memory pointed to by this
|
||||
/// # 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<T>(&self, offset: usize) -> &T {
|
||||
let ptr: *const T = self.raw_ptr_at_offset(offset as u64);
|
||||
|
|
@ -132,9 +132,10 @@ impl MemoryRegion {
|
|||
|
||||
/// Creates a reference from a given offset.
|
||||
///
|
||||
/// SAFETY: Caller must ensure that this is the only reference to the memory pointed
|
||||
/// # 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<T>(&self, offset: usize) -> &mut T {
|
||||
pub unsafe fn as_mut_ref_at_offset<T>(&mut self, offset: usize) -> &mut T {
|
||||
let ptr: *const T = self.raw_ptr_at_offset(offset as u64);
|
||||
assert!(ptr.is_aligned(), "");
|
||||
// SAFETY:
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ impl<T> PhysicalBox<[T]> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_vec(mut vec: Vec<T>) -> Self {
|
||||
pub fn from_vec(vec: Vec<T>) -> Self {
|
||||
let len = vec.len();
|
||||
let layout = core::alloc::Layout::array::<T>(len).expect("Layout overflow");
|
||||
|
||||
|
|
@ -117,6 +117,10 @@ impl<T> PhysicalBox<[T]> {
|
|||
pub fn len(&self) -> usize {
|
||||
(**self).len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T> Index<I> for PhysicalBox<[T]>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ impl<T> DerefMut for MutexGuard<'_, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Mutex<T> {
|
||||
impl<'a, T> Mutex<T> {
|
||||
pub fn new(data: T) -> Mutex<T> {
|
||||
Mutex {
|
||||
cap: syscall::mutex_create().unwrap(),
|
||||
|
|
@ -58,7 +58,7 @@ impl<T> Mutex<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn lock(&self) -> MutexGuard<T> {
|
||||
pub fn lock(&'a self) -> MutexGuard<'a, T> {
|
||||
syscall::mutex_lock(&self.cap).unwrap();
|
||||
|
||||
MutexGuard { mutex: self }
|
||||
|
|
@ -70,3 +70,12 @@ impl<T> Drop for MutexGuard<'_, T> {
|
|||
syscall::mutex_release(&self.mutex.cap).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for Mutex<T>
|
||||
where
|
||||
T: Default,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self::new(T::default())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ use core::ffi::c_void;
|
|||
#[cfg(feature = "hosted")]
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[must_use]
|
||||
fn syscall<T>(id: u64, req: &T) -> Result<(), ZError> {
|
||||
unsafe {
|
||||
let resp = zion::SysCall1(id, req as *const T as *const c_void);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ struct TaskWaker {
|
|||
}
|
||||
|
||||
impl TaskWaker {
|
||||
fn new(task_id: TaskId, task_queue: Arc<Mutex<VecDeque<TaskId>>>) -> Waker {
|
||||
fn create_waker(task_id: TaskId, task_queue: Arc<Mutex<VecDeque<TaskId>>>) -> Waker {
|
||||
Waker::from(Arc::new(TaskWaker {
|
||||
task_id,
|
||||
task_queue,
|
||||
|
|
@ -69,6 +69,7 @@ impl Wake for TaskWaker {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Executor {
|
||||
tasks: Arc<Mutex<BTreeMap<TaskId, Task>>>,
|
||||
// TODO: Consider a better datastructure for this.
|
||||
|
|
@ -78,11 +79,7 @@ pub struct Executor {
|
|||
|
||||
impl Executor {
|
||||
pub fn new() -> Executor {
|
||||
Executor {
|
||||
tasks: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
task_queue: Arc::new(Mutex::new(VecDeque::new())),
|
||||
waker_cache: BTreeMap::new(),
|
||||
}
|
||||
Executor::default()
|
||||
}
|
||||
|
||||
pub fn spawn(&mut self, task: Task) {
|
||||
|
|
@ -100,7 +97,7 @@ impl Executor {
|
|||
let waker = self
|
||||
.waker_cache
|
||||
.entry(task_id)
|
||||
.or_insert_with(|| TaskWaker::new(task_id, self.task_queue.clone()));
|
||||
.or_insert_with(|| TaskWaker::create_waker(task_id, self.task_queue.clone()));
|
||||
let mut ctx = Context::from_waker(waker);
|
||||
match task.poll(&mut ctx) {
|
||||
Poll::Ready(()) => {
|
||||
|
|
|
|||
|
|
@ -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 u64, raw_main as u64, 0).unwrap();
|
||||
syscall::thread_start(&cap, entry_point as usize as u64, raw_main as u64, 0).unwrap();
|
||||
|
||||
JoinHandle { cap }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ use alloc::vec::Vec;
|
|||
use mammoth::{cap::Capability, mem::MemoryRegion, syscall, zion::ZError};
|
||||
|
||||
use crate::header::{
|
||||
PciCapabilityPointer, PciDeviceHeader, PciHeaderType, PciMsiCapability, PciMsiControl,
|
||||
get_header_type,
|
||||
PciCapabilityPointer, PciDeviceHeader, PciHeaderType, PciMsiCapability, get_header_type,
|
||||
};
|
||||
|
||||
pub struct PciDevice {
|
||||
|
|
@ -11,7 +10,7 @@ pub struct PciDevice {
|
|||
}
|
||||
|
||||
impl PciDevice {
|
||||
pub fn from(mut memory_region: MemoryRegion) -> Result<Self, ZError> {
|
||||
pub fn from(memory_region: MemoryRegion) -> Result<Self, ZError> {
|
||||
match get_header_type(&memory_region)? {
|
||||
PciHeaderType::Device => {}
|
||||
t => {
|
||||
|
|
|
|||
|
|
@ -10,10 +10,12 @@ static mut YELLOWSTONE_INIT: Option<YellowstoneClient> = None;
|
|||
|
||||
pub fn from_init_endpoint() -> &'static mut YellowstoneClient {
|
||||
unsafe {
|
||||
if let None = YELLOWSTONE_INIT {
|
||||
#[allow(static_mut_refs)]
|
||||
if YELLOWSTONE_INIT.is_none() {
|
||||
YELLOWSTONE_INIT = Some(YellowstoneClient::new(Capability::take(INIT_ENDPOINT)));
|
||||
}
|
||||
|
||||
#[allow(static_mut_refs)]
|
||||
YELLOWSTONE_INIT.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@ 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();
|
||||
|
|
@ -27,7 +31,11 @@ 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();
|
||||
|
|
@ -63,7 +71,9 @@ 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();
|
||||
|
|
@ -79,7 +89,11 @@ mod tests {
|
|||
#[test]
|
||||
fn nested_serialization() -> Result<(), ZError> {
|
||||
let nested = Nested {
|
||||
basic: Basic { unsigned_int: 82, signed_int: -1234, strn: "abc".to_string() },
|
||||
basic: Basic {
|
||||
unsigned_int: 82,
|
||||
signed_int: -1234,
|
||||
strn: "abc".to_string(),
|
||||
},
|
||||
cap1: Cap { cap: 37 },
|
||||
cap2: Cap { cap: 39 },
|
||||
};
|
||||
|
|
@ -90,7 +104,6 @@ mod tests {
|
|||
|
||||
let parsed = Nested::parse(&buf, 0, &caps)?;
|
||||
|
||||
|
||||
assert!(parsed == nested);
|
||||
|
||||
Ok(())
|
||||
|
|
@ -99,8 +112,18 @@ 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(), },],
|
||||
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 }],
|
||||
};
|
||||
|
||||
|
|
@ -110,12 +133,8 @@ mod tests {
|
|||
|
||||
let parsed = RepeatedNested::parse(&buf, 0, &caps)?;
|
||||
|
||||
|
||||
assert!(parsed == nested);
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,19 @@ pub struct ByteBuffer<const N: usize> {
|
|||
buffer: Box<[u8; N]>,
|
||||
}
|
||||
|
||||
impl<const N: usize> ByteBuffer<N> {
|
||||
pub fn new() -> Self {
|
||||
impl<const N: usize> Default for ByteBuffer<N> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
buffer: Box::new([0; N]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> ByteBuffer<N> {
|
||||
pub fn new() -> Self {
|
||||
ByteBuffer::default()
|
||||
}
|
||||
|
||||
pub fn size(&self) -> u64 {
|
||||
N as u64
|
||||
}
|
||||
|
|
@ -54,7 +61,7 @@ impl<const N: usize> ByteBuffer<N> {
|
|||
if (len + offset) > N {
|
||||
return Err(ZError::BUFFER_SIZE);
|
||||
}
|
||||
Ok(alloc::str::from_utf8(&self.buffer[offset..offset + len])
|
||||
.map_err(|_| ZError::INVALID_ARGUMENT)?)
|
||||
alloc::str::from_utf8(&self.buffer[offset..offset + len])
|
||||
.map_err(|_| ZError::INVALID_ARGUMENT)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,5 +34,5 @@ pub fn call_endpoint<Req: YunqMessage, Resp: YunqMessage, const N: usize>(
|
|||
return Err(ZError::from(resp_code));
|
||||
}
|
||||
|
||||
Ok(Resp::parse_from_request(&byte_buffer, &cap_buffer)?)
|
||||
Resp::parse_from_request(byte_buffer, &cap_buffer)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ pub fn parse_repeated_message<T: YunqMessage, const N: usize>(
|
|||
buf: &ByteBuffer<N>,
|
||||
mut offset: usize,
|
||||
len: usize,
|
||||
caps: &Vec<z_cap_t>,
|
||||
caps: &[z_cap_t],
|
||||
) -> Result<Vec<T>, ZError> {
|
||||
let mut repeated = Vec::new();
|
||||
for _ in 0..len {
|
||||
|
|
@ -43,18 +43,18 @@ pub fn parse_repeated_message<T: YunqMessage, const N: usize>(
|
|||
pub fn serialize_repeated<T: Copy, const N: usize>(
|
||||
buf: &mut ByteBuffer<N>,
|
||||
offset: usize,
|
||||
data: &Vec<T>,
|
||||
data: &[T],
|
||||
) -> Result<usize, ZError> {
|
||||
for i in 0..data.len() {
|
||||
buf.write_at(offset + (i * size_of::<T>()), data[i])?;
|
||||
for (i, val) in data.iter().enumerate() {
|
||||
buf.write_at(offset + (i * size_of::<T>()), val)?;
|
||||
}
|
||||
Ok(offset + (data.len() * size_of::<T>()))
|
||||
Ok(offset + size_of_val(data))
|
||||
}
|
||||
|
||||
pub fn serialize_repeated_message<T: YunqMessage, const N: usize>(
|
||||
buf: &mut ByteBuffer<N>,
|
||||
mut offset: usize,
|
||||
data: &Vec<T>,
|
||||
data: &[T],
|
||||
caps: &mut Vec<z_cap_t>,
|
||||
) -> Result<usize, ZError> {
|
||||
for item in data {
|
||||
|
|
@ -76,14 +76,14 @@ pub trait YunqMessage {
|
|||
fn parse<const N: usize>(
|
||||
buf: &ByteBuffer<N>,
|
||||
offset: usize,
|
||||
caps: &Vec<z_cap_t>,
|
||||
caps: &[z_cap_t],
|
||||
) -> Result<Self, ZError>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
fn parse_from_request<const N: usize>(
|
||||
buf: &ByteBuffer<N>,
|
||||
caps: &Vec<z_cap_t>,
|
||||
caps: &[z_cap_t],
|
||||
) -> Result<Self, ZError>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -92,7 +92,7 @@ pub trait YunqMessage {
|
|||
return Err(ZError::INVALID_RESPONSE);
|
||||
}
|
||||
|
||||
Ok(Self::parse(&buf, 16, &caps)?)
|
||||
Self::parse(buf, 16, caps)
|
||||
}
|
||||
|
||||
fn serialize<const N: usize>(
|
||||
|
|
@ -109,7 +109,7 @@ pub trait YunqMessage {
|
|||
caps: &mut Vec<z_cap_t>,
|
||||
) -> Result<usize, ZError> {
|
||||
buf.write_at(0, SENTINEL)?;
|
||||
buf.write_at(8, request_id as u64)?;
|
||||
buf.write_at(8, request_id)?;
|
||||
|
||||
let length = self.serialize(buf, 16, caps)?;
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ impl YunqMessage for Empty {
|
|||
fn parse<const N: usize>(
|
||||
_buf: &ByteBuffer<N>,
|
||||
_offset: usize,
|
||||
_caps: &Vec<z_cap_t>,
|
||||
_caps: &[z_cap_t],
|
||||
) -> Result<Self, ZError>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
|
|||
|
|
@ -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::<u64>(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,12 +113,10 @@ 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")
|
||||
}
|
||||
}
|
||||
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ impl Command {
|
|||
command: SataCommand::DmaReadExt,
|
||||
lba,
|
||||
sector_cnt: lba_count,
|
||||
paddr: paddr,
|
||||
paddr,
|
||||
memory_region: None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,9 +44,8 @@ impl PortController {
|
|||
};
|
||||
|
||||
// This leaves space for 8 prdt entries.
|
||||
for i in 0..32 {
|
||||
command_list[i].command_table_base_addr =
|
||||
(command_paddr + 0x500) + (0x100 * (i as u64));
|
||||
for (i, header) in command_list.iter_mut().enumerate() {
|
||||
header.command_table_base_addr = (command_paddr + 0x500) + (0x100 * (i as u64));
|
||||
}
|
||||
|
||||
let command_slots = array::from_fn(|_| Arc::new(Mutex::new(CommandStatus::Empty)));
|
||||
|
|
|
|||
|
|
@ -16,15 +16,16 @@ impl Framebuffer {
|
|||
})
|
||||
}
|
||||
|
||||
fn draw_pixel(&self, row: u32, col: u32, pixel: u32) {
|
||||
fn draw_pixel(&mut 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(&self, glyph: &[u8], row: u32, col: u32) {
|
||||
pub fn draw_glyph(&mut 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 {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub struct Psf {
|
|||
|
||||
impl Psf {
|
||||
pub fn new(path: &str) -> Result<Self, ZError> {
|
||||
let file = File::open(&path)?;
|
||||
let file = File::open(path)?;
|
||||
|
||||
let header = file.slice()[0..core::mem::size_of::<PsfHeader>()]
|
||||
.as_ptr()
|
||||
|
|
|
|||
|
|
@ -62,10 +62,8 @@ impl Terminal {
|
|||
}
|
||||
|
||||
fn write_line(&mut self, line: &str) {
|
||||
let mut col = 0;
|
||||
for c in line.chars() {
|
||||
self.console.write_char(c, self.row, col);
|
||||
col += 1;
|
||||
for (col, c) in line.chars().enumerate() {
|
||||
self.console.write_char(c, self.row, col as u32);
|
||||
}
|
||||
|
||||
self.row += 1
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ static mut VFS_CLIENT: Option<VFSClient> = None;
|
|||
|
||||
fn get_client() -> &'static mut VFSClient {
|
||||
unsafe {
|
||||
if let None = VFS_CLIENT {
|
||||
#[allow(static_mut_refs)]
|
||||
if VFS_CLIENT.is_none() {
|
||||
let endpoint_cap = yellowstone_yunq::from_init_endpoint()
|
||||
.get_endpoint(&yellowstone_yunq::GetEndpointRequest {
|
||||
endpoint_name: "victoriafalls".to_string(),
|
||||
|
|
@ -21,6 +22,7 @@ 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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ impl VFSServerHandler for VictoriaFallsServerImpl {
|
|||
|
||||
let mut inode_num = 2; // Start with root.
|
||||
|
||||
while let Some(path_token) = tokens.next() {
|
||||
for path_token in tokens {
|
||||
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.
|
||||
|
||||
while let Some(path_token) = tokens.next() {
|
||||
for path_token in tokens {
|
||||
inode_num = self.find_path_in_dir(inode_num, path_token)?;
|
||||
}
|
||||
|
||||
|
|
|
|||
71
rust/sys/voyageurs/src/xhci/data_structures/command_trb.rs
Normal file
71
rust/sys/voyageurs/src/xhci/data_structures/command_trb.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
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<EnableSlotCommand> 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<AddressDeviceCommand> 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<NoOpCommand> 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<CommandTrb> for TransferRequestBlock {
|
||||
fn from(value: CommandTrb) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
|
@ -18,10 +18,10 @@ pub struct EventRingSegmentTableEntry {
|
|||
}
|
||||
|
||||
impl EventRingSegmentTableEntry {
|
||||
pub fn from_trb_ring(&mut self, trb_ring: &TrbRingSegment) {
|
||||
pub fn update_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 % 64 == 0);
|
||||
assert!(self.ring_segment_base_address.is_multiple_of(64));
|
||||
unsafe {
|
||||
core::ptr::write_volatile(
|
||||
&mut self.ring_segment_size as *mut u64,
|
||||
|
|
|
|||
139
rust/sys/voyageurs/src/xhci/data_structures/event_trb.rs
Normal file
139
rust/sys/voyageurs/src/xhci/data_structures/event_trb.rs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
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<TransferRequestBlock> 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,18 @@
|
|||
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::*;
|
||||
|
|
|
|||
|
|
@ -75,29 +75,6 @@ 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
|
||||
|
|
@ -141,138 +118,3 @@ 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 {}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use mammoth::physical_box::PhysicalBox;
|
|||
use crate::xhci::{
|
||||
data_structures::{
|
||||
DeviceContext, EndpointContextFields, EndpointState, EndpointType, InputContext,
|
||||
TRDequeuePointer, TrbTransferEvent,
|
||||
TRDequeuePointer, TransferEvent,
|
||||
},
|
||||
registers::DoorbellPointer,
|
||||
trb_ring::TrbRing,
|
||||
|
|
@ -20,22 +20,27 @@ impl DeviceContextBaseArray {
|
|||
|
||||
pub struct DeviceSlot {
|
||||
device_context: PhysicalBox<DeviceContext>,
|
||||
endpoint_0_transfer_ring: TrbRing<TrbTransferEvent>,
|
||||
endpoint_0_transfer_ring: TrbRing<TransferEvent>,
|
||||
doorbell: DoorbellPointer,
|
||||
}
|
||||
|
||||
impl DeviceSlot {
|
||||
fn new() -> Self {
|
||||
fn new(doorbell: DoorbellPointer) -> 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<DeviceSlot>]>,
|
||||
doorbells: Box<[DoorbellPointer]>,
|
||||
doorbells: Box<[Option<DoorbellPointer>]>,
|
||||
}
|
||||
|
||||
impl DeviceSlotManager {
|
||||
|
|
@ -49,7 +54,7 @@ impl DeviceSlotManager {
|
|||
slots: core::iter::repeat_with(|| None)
|
||||
.take(max_slots as usize)
|
||||
.collect(),
|
||||
doorbells,
|
||||
doorbells: doorbells.into_iter().map(|d| Some(d)).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +71,11 @@ impl DeviceSlotManager {
|
|||
port_number: u8,
|
||||
) -> PhysicalBox<InputContext> {
|
||||
// TODO: Ensure alignment
|
||||
let device_slot = DeviceSlot::new();
|
||||
let device_slot = DeviceSlot::new(
|
||||
self.doorbells[(slot_id - 1) as usize]
|
||||
.take()
|
||||
.expect("Slot already allocated."),
|
||||
);
|
||||
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’.
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
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::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::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::device_context_base_array::DeviceSlotManager;
|
||||
use crate::xhci::interrupter::Interrupter;
|
||||
use crate::xhci::registers::DoorbellPointer;
|
||||
|
|
@ -40,7 +37,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 as usize);
|
||||
let (operational, capabilities) = HostControllerOperationalWrapper::new(address);
|
||||
|
||||
let max_slots = capabilities.params_1.max_device_slots();
|
||||
let doorbell_physical = address + capabilities.doorbell_offset as usize;
|
||||
|
|
@ -153,38 +150,49 @@ impl XHCIDriver {
|
|||
}
|
||||
|
||||
pub fn interrupt_loop(self: Arc<Self>, spawner: Spawner) {
|
||||
let completion_handler = |trb: TransferRequestBlock| {
|
||||
let completion_handler = |trb| {
|
||||
self.clone().handle_completion(spawner.clone(), trb);
|
||||
};
|
||||
|
||||
self.interrupter.lock().interrupt_loop(completion_handler);
|
||||
}
|
||||
|
||||
fn handle_completion(self: Arc<XHCIDriver>, spawner: Spawner, trb: TransferRequestBlock) {
|
||||
match trb.trb_type() {
|
||||
TrbType::TransferEvent => {
|
||||
todo!("Handle Transfer")
|
||||
fn handle_completion(self: Arc<XHCIDriver>, spawner: Spawner, trb: EventTrb) {
|
||||
match trb {
|
||||
EventTrb::Transfer(trb) => {
|
||||
mammoth::debug!("Unhandled transfer event: {:?}", trb);
|
||||
}
|
||||
TrbType::CommandCompletionEvent => {
|
||||
EventTrb::CommandCompletion(trb) => {
|
||||
self.command_ring
|
||||
.lock()
|
||||
.trb_ring
|
||||
.handle_completion(TrbCommandCompletion::from_trb(trb));
|
||||
.handle_completion(trb, trb.command_trb_pointer() as usize);
|
||||
}
|
||||
TrbType::PortStatusChangeEvent => {
|
||||
let trb = TrbPortStatusChangeEvent::from_trb(trb);
|
||||
EventTrb::PortStatusChange(trb) => {
|
||||
let self_clone = self.clone();
|
||||
spawner.spawn(Task::new(async move {
|
||||
self_clone.port_status_change(trb).await
|
||||
}));
|
||||
}
|
||||
_ => {
|
||||
panic!("Unhandled event type: {:?}", trb.trb_type());
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_command(&self, trb: impl TypedTrb) -> TrbCommandCompletion {
|
||||
async fn send_command(&self, trb: CommandTrb) -> CommandCompletionEvent {
|
||||
// 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
|
||||
|
|
@ -194,9 +202,9 @@ impl XHCIDriver {
|
|||
#[cfg(feature = "debug")]
|
||||
mammoth::debug!("Sending no op command.");
|
||||
|
||||
let result = self.send_command(TrbNoOp::new()).await;
|
||||
let result = self.send_command(NoOpCommand::new().into()).await;
|
||||
|
||||
assert!(result.completion_code() == CommandCompletionCode::Success.into_bits());
|
||||
assert_eq!(result.completion_code(), CommandCompletionCode::Success);
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
mammoth::debug!("Successfully tested no op command.");
|
||||
|
|
@ -221,15 +229,12 @@ impl XHCIDriver {
|
|||
}
|
||||
}
|
||||
|
||||
async fn port_status_change(self: Arc<Self>, status_change: TrbPortStatusChangeEvent) {
|
||||
async fn port_status_change(self: Arc<Self>, status_change: PortStatusChangeEvent) {
|
||||
// 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 as usize)
|
||||
.status_and_control;
|
||||
let port_status = self.operational.get_port(port_index).status_and_control;
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
mammoth::debug!("Port status change for port {}", port_id);
|
||||
|
|
@ -248,8 +253,8 @@ impl XHCIDriver {
|
|||
#[cfg(feature = "debug")]
|
||||
mammoth::debug!("Enabling slot.");
|
||||
|
||||
let resp = self.send_command(TrbEnableSlotCommand::new()).await;
|
||||
assert!(resp.completion_code() == CommandCompletionCode::Success.into_bits());
|
||||
let resp = self.send_command(EnableSlotCommand::new().into()).await;
|
||||
assert_eq!(resp.completion_code(), CommandCompletionCode::Success);
|
||||
|
||||
let slot = resp.slot_id();
|
||||
|
||||
|
|
@ -266,11 +271,12 @@ impl XHCIDriver {
|
|||
|
||||
let resp = self
|
||||
.send_command(
|
||||
TrbAddressDeviceCommand::new()
|
||||
AddressDeviceCommand::new()
|
||||
.with_slot_id(slot)
|
||||
.with_input_context_pointer(input_context.physical_address() as u64),
|
||||
.with_input_context_pointer(input_context.physical_address() as u64)
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
assert!(resp.completion_code() == CommandCompletionCode::Success.into_bits());
|
||||
assert_eq!(resp.completion_code(), CommandCompletionCode::Success);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use alloc::vec::Vec;
|
||||
|
||||
use crate::xhci::{
|
||||
data_structures::{EventRingSegmentTable, TransferRequestBlock, TrbRingSegment},
|
||||
data_structures::{EventRingSegmentTable, EventTrb, TransferRequestBlock, TrbRingSegment},
|
||||
trb_ring::TrbPointer,
|
||||
};
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ impl EventRing {
|
|||
trb_pointer: TrbPointer::default(),
|
||||
};
|
||||
|
||||
event_ring.segment_table[0].from_trb_ring(&event_ring.segments[0]);
|
||||
event_ring.segment_table[0].update_from_trb_ring(&event_ring.segments[0]);
|
||||
|
||||
event_ring
|
||||
}
|
||||
|
|
@ -58,13 +58,13 @@ impl EventRing {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_next(&mut self) -> Option<TransferRequestBlock> {
|
||||
pub fn get_next(&mut self) -> Option<EventTrb> {
|
||||
let curr = self.current_trb();
|
||||
if curr.cycle() != self.cycle_bit {
|
||||
None
|
||||
} else {
|
||||
self.increment_pointer();
|
||||
Some(curr)
|
||||
Some(curr.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use core::ptr::NonNull;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use mammoth::cap::Capability;
|
||||
|
||||
use crate::xhci::{
|
||||
data_structures::TransferRequestBlock,
|
||||
data_structures::{EventTrb, TransferRequestBlock},
|
||||
event_ring::EventRing,
|
||||
registers::{InterrupterModeration, InterrupterRegisterSet, InterrupterRegisters},
|
||||
};
|
||||
|
|
@ -48,17 +47,14 @@ impl Interrupter {
|
|||
self.register_set.enable_interrupts();
|
||||
}
|
||||
|
||||
pub fn interrupt_loop(&mut self, completion_handler: impl Fn(TransferRequestBlock) -> ()) {
|
||||
pub fn interrupt_loop(&mut self, completion_handler: impl Fn(EventTrb)) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use core::ptr::NonNull;
|
||||
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use alloc::boxed::Box;
|
||||
use bitfield_struct::bitfield;
|
||||
use volatile::VolatileRef;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use mammoth::sync::Mutex;
|
|||
|
||||
use crate::xhci::{
|
||||
data_structures::{
|
||||
TransferRequestBlock, TrbCommandCompletion, TrbLink, TrbRingSegment, TypedTrb,
|
||||
CommandCompletionEvent, CommandTrb, TransferRequestBlock, TrbLink, TrbRingSegment, TypedTrb,
|
||||
},
|
||||
registers::DoorbellPointer,
|
||||
};
|
||||
|
|
@ -20,11 +20,11 @@ struct TrbFutureState<T> {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TrbFuture<T: TypedTrb> {
|
||||
pub struct TrbFuture<T> {
|
||||
state: Arc<Mutex<TrbFutureState<T>>>,
|
||||
}
|
||||
|
||||
impl<T: TypedTrb> TrbFuture<T> {
|
||||
impl<T> TrbFuture<T> {
|
||||
fn new(paddr: usize) -> Self {
|
||||
Self {
|
||||
state: Arc::new(Mutex::new(TrbFutureState {
|
||||
|
|
@ -36,7 +36,7 @@ impl<T: TypedTrb> TrbFuture<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: TypedTrb> Future for TrbFuture<T> {
|
||||
impl<T: Copy> Future for TrbFuture<T> {
|
||||
type Output = T;
|
||||
|
||||
fn poll(
|
||||
|
|
@ -70,14 +70,14 @@ impl TrbPointer {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct TrbRing<T: TypedTrb> {
|
||||
pub struct TrbRing<T> {
|
||||
segments: Vec<TrbRingSegment>,
|
||||
enqueue_pointer: TrbPointer,
|
||||
cycle_bit: bool,
|
||||
pending_futures: VecDeque<TrbFuture<T>>,
|
||||
}
|
||||
|
||||
impl<T: TypedTrb> TrbRing<T> {
|
||||
impl<T: Clone> TrbRing<T> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
// TODO: What size and count should this be.
|
||||
|
|
@ -147,17 +147,15 @@ impl<T: TypedTrb> TrbRing<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn handle_completion(&mut self, completion_trb: T) {
|
||||
let trb = completion_trb.to_trb();
|
||||
let paddr = trb.parameter() as usize;
|
||||
pub fn handle_completion(&mut self, completion_trb: T, physical_address: usize) {
|
||||
let completion = self.pending_futures.pop_front().unwrap();
|
||||
let mut completion = completion.state.lock();
|
||||
// TODO: Handle recovery scenarios here.
|
||||
assert!(
|
||||
completion.physical_address == paddr,
|
||||
completion.physical_address == physical_address,
|
||||
"Got an unexpected command completion. Expected: {:0x}, Got: {:0x}",
|
||||
completion.physical_address,
|
||||
paddr
|
||||
physical_address
|
||||
);
|
||||
completion.response = Some(completion_trb);
|
||||
|
||||
|
|
@ -168,7 +166,7 @@ impl<T: TypedTrb> TrbRing<T> {
|
|||
}
|
||||
|
||||
pub struct CommandRing {
|
||||
pub trb_ring: TrbRing<TrbCommandCompletion>,
|
||||
pub trb_ring: TrbRing<CommandCompletionEvent>,
|
||||
doorbell: DoorbellPointer,
|
||||
}
|
||||
|
||||
|
|
@ -181,8 +179,8 @@ impl CommandRing {
|
|||
}
|
||||
|
||||
// We have to explicitly return a future her
|
||||
pub fn enqueue_command(&mut self, command: impl TypedTrb) -> TrbFuture<TrbCommandCompletion> {
|
||||
let fut = self.trb_ring.enqueue_trb(command.to_trb());
|
||||
pub fn enqueue_command(&mut self, command: CommandTrb) -> TrbFuture<CommandCompletionEvent> {
|
||||
let fut = self.trb_ring.enqueue_trb(command.into());
|
||||
// Command Doorbell is always 0.
|
||||
self.doorbell.ring(0);
|
||||
fut
|
||||
|
|
|
|||
|
|
@ -57,9 +57,8 @@ impl YellowstoneServerContext {
|
|||
|
||||
pub fn wait(&self, service: &str) -> Result<(), ZError> {
|
||||
loop {
|
||||
match self.service_map.lock().get(service) {
|
||||
Some(_) => return Ok(()),
|
||||
None => {}
|
||||
if self.service_map.lock().get(service).is_some() {
|
||||
return Ok(());
|
||||
}
|
||||
self.registration_semaphore.wait().unwrap();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ CARGO_SYS_ROOT="${DIR}/../sysroot/"
|
|||
pushd "${DIR}/../rust"
|
||||
|
||||
for BIN in ${DIR}/../rust/usr/*/; do
|
||||
cargo install --offline --force --path "${BIN}" --root $CARGO_USR_ROOT
|
||||
cargo install --force --path "${BIN}" --root $CARGO_USR_ROOT
|
||||
done
|
||||
|
||||
for BIN in ${DIR}/../rust/sys/*/; do
|
||||
cargo install --offline --all-features --force --path "${BIN}" --root $CARGO_SYS_ROOT
|
||||
cargo install --all-features --force --path "${BIN}" --root $CARGO_SYS_ROOT
|
||||
done
|
||||
popd
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ fn parse_field(field: &Field) -> TokenStream {
|
|||
let rep_offset = buf.at::<u32>(yunq::message::field_offset(offset, #ind))?;
|
||||
let rep_len = buf.at::<u32>(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<N>,
|
||||
offset: usize,
|
||||
caps: &mut alloc::vec::Vec<z_cap_t>,
|
||||
caps: &mut Vec<z_cap_t>,
|
||||
) -> Result<usize, ZError> {
|
||||
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 + 0, yunq::message::MESSAGE_IDENT)?;
|
||||
buf.write_at(offset, yunq::message::MESSAGE_IDENT)?;
|
||||
buf.write_at(offset + 4, core_size)?;
|
||||
buf.write_at(offset + 8, next_extension)?;
|
||||
buf.write_at(offset + 12, 0 as u32)?;
|
||||
buf.write_at(offset + 12, 0_u32)?;
|
||||
Ok(next_extension as usize)
|
||||
}
|
||||
}
|
||||
|
|
@ -200,12 +200,12 @@ fn generate_parse(message: &Message) -> TokenStream {
|
|||
fn parse<const N: usize>(
|
||||
buf: &yunq::ByteBuffer<N>,
|
||||
offset: usize,
|
||||
caps: &alloc::vec::Vec<z_cap_t>,
|
||||
caps: &[z_cap_t],
|
||||
) -> Result<Self, ZError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
if buf.at::<u32>(offset + 0)? != yunq::message::MESSAGE_IDENT {
|
||||
if buf.at::<u32>(offset)? != yunq::message::MESSAGE_IDENT {
|
||||
mammoth::debug!("Expected IDENT at offest {:#x}, got {:#x}", offset, buf.at::<u32>(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.resize(0, 0);
|
||||
cap_buffer.clear();
|
||||
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.resize(0, 0);
|
||||
cap_buffer.clear();
|
||||
// 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.resize(0, 0);
|
||||
cap_buffer.clear();
|
||||
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.resize(0, 0);
|
||||
cap_buffer.clear();
|
||||
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.resize(0, 0);
|
||||
cap_buffer.clear();
|
||||
// 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.resize(0, 0);
|
||||
cap_buffer.clear();
|
||||
let resp_len = resp.serialize_as_request(0, byte_buffer, cap_buffer)?;
|
||||
Ok(resp_len)
|
||||
},
|
||||
|
|
@ -547,6 +547,7 @@ 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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue