Skip to content

Commit

Permalink
add macro to read config fields
Browse files Browse the repository at this point in the history
Ensures that the offset and type match.
  • Loading branch information
fkm3 committed Dec 3, 2024
1 parent f8a3df1 commit 009882a
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
7 changes: 5 additions & 2 deletions src/device/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use crate::hal::{BufferDirection, Dma, Hal};
use crate::queue::VirtQueue;
use crate::transport::read_config_field;
use crate::transport::Transport;
use crate::volatile::{ReadOnly, Volatile, WriteOnly};
use crate::{pages, Error, Result, PAGE_SIZE};
Expand Down Expand Up @@ -44,11 +45,12 @@ impl<H: Hal, T: Transport> VirtIOGpu<H, T> {
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);

// read configuration space
let events_read = transport.read_config_space::<u32>(offset_of!(Config, events_read))?;
let events_read = read_config_field!(transport, Config, events_read)?;
// let events_read = transport.read_config_space::<u32>(offset_of!(Config, events_read))?;
let num_scanouts = transport.read_config_space::<u32>(offset_of!(Config, num_scanouts))?;
info!(
"events_read: {:#x}, num_scanouts: {:#x}",
events_read, num_scanouts
events_read.0, num_scanouts
);

let control_queue = VirtQueue::new(
Expand Down Expand Up @@ -292,6 +294,7 @@ impl<H: Hal, T: Transport> Drop for VirtIOGpu<H, T> {
}
}

#[derive(Default, zerocopy::FromBytes)]
#[repr(C)]
struct Config {
/// Signals pending events to the driver。
Expand Down
25 changes: 25 additions & 0 deletions src/transport/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,31 @@ pub trait Transport {
) -> Result<()>;
}

/// Reads a value from the device config space. The parameters are (1) an instance of `Transport`,
/// (2) a type describing the config's memory layout, and (3) a field of that type.
macro_rules! read_config_field {

Check warning on line 117 in src/transport/mod.rs

View workflow job for this annotation

GitHub Actions / build

unused macro definition: `read_config_field`

Check warning on line 117 in src/transport/mod.rs

View workflow job for this annotation

GitHub Actions / build

unused macro definition: `read_config_field`
($transport:expr, $config_type:ty, $field:ident) => {{
// We need to know the config field's type, but there is nothing like C++'s "decltype" in
// Rust. Workaround it by creating an instance of the config and a variable `f` initialized
// to the field of that instance. That constrains `f`'s type to match the field's type.
// Then, assign the result of `Transport::read_config_space` to `f` to constrain its type
// parameter to be of the same type. When optimizations are enabled, the extra variables
// and initialization will be elided.
let c: $config_type = FromZeros::new_zeroed();
#[allow(unused_assignments)]
let mut f = c.$field;
match $transport.read_config_space(offset_of!($config_type, $field)) {
Ok(x) => {
f = x;
Ok(f)
}
Err(e) => Err(e),
}
}};
}

pub(crate) use read_config_field;

Check warning on line 138 in src/transport/mod.rs

View workflow job for this annotation

GitHub Actions / build

unused import: `read_config_field`

Check warning on line 138 in src/transport/mod.rs

View workflow job for this annotation

GitHub Actions / build

unused import: `read_config_field`

bitflags! {
/// The device status field. Writing 0 into this field resets the device.
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
Expand Down
6 changes: 3 additions & 3 deletions src/volatile.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// An MMIO register which can only be read from.
#[derive(Default)]
#[derive(Default, zerocopy::FromBytes)]
#[repr(transparent)]
pub struct ReadOnly<T: Copy>(pub(crate) T);

Expand All @@ -11,12 +11,12 @@ impl<T: Copy> ReadOnly<T> {
}

/// An MMIO register which can only be written to.
#[derive(Default)]
#[derive(Default, zerocopy::FromBytes)]
#[repr(transparent)]
pub struct WriteOnly<T: Copy>(pub(crate) T);

/// An MMIO register which may be both read and written.
#[derive(Default)]
#[derive(Default, zerocopy::FromBytes)]
#[repr(transparent)]
pub struct Volatile<T: Copy>(T);

Expand Down

0 comments on commit 009882a

Please sign in to comment.