Skip to content

Commit b2eb08b

Browse files
authored
Merge pull request #170 from rcore-os/safereg
Add macros to read or write config space in a type safe way
2 parents 4374e81 + f4605c9 commit b2eb08b

File tree

15 files changed

+417
-283
lines changed

15 files changed

+417
-283
lines changed

src/config.rs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
//! Types and macros for VirtIO device configuration space.
2+
3+
use crate::{transport::Transport, Error};
4+
use zerocopy::{FromBytes, Immutable, IntoBytes};
5+
6+
/// A configuration space register from which the driver can only read.
7+
#[derive(Default, FromBytes, Immutable, IntoBytes)]
8+
#[repr(transparent)]
9+
pub struct ReadOnly<T: Copy + FromBytes>(pub T);
10+
11+
impl<T: Copy + FromBytes> ReadOnly<T> {
12+
/// Constructs a new instance for testing.
13+
pub const fn new(value: T) -> Self {
14+
Self(value)
15+
}
16+
}
17+
18+
/// A configuration space register to which the driver can only write.
19+
#[derive(Default, FromBytes, Immutable, IntoBytes)]
20+
#[repr(transparent)]
21+
pub struct WriteOnly<T: Copy + Immutable + IntoBytes>(pub T);
22+
23+
impl<T: Copy + Immutable + IntoBytes> WriteOnly<T> {
24+
/// Constructs a new instance for testing.
25+
pub const fn new(value: T) -> Self {
26+
Self(value)
27+
}
28+
}
29+
30+
/// A configuration space register which the driver may both read and write.
31+
#[derive(Default, FromBytes, Immutable, IntoBytes)]
32+
#[repr(transparent)]
33+
pub struct ReadWrite<T: Copy + FromBytes + Immutable + IntoBytes>(pub T);
34+
35+
impl<T: Copy + FromBytes + Immutable + IntoBytes> ReadWrite<T> {
36+
/// Constructs a new instance for testing.
37+
pub const fn new(value: T) -> Self {
38+
Self(value)
39+
}
40+
}
41+
42+
/// Marker trait for configuration space registers from which the driver may read.
43+
pub trait ConfigReadable<T> {}
44+
45+
/// Marker trait for configuration space registers to which the driver may write.
46+
pub trait ConfigWritable<T> {}
47+
48+
impl<T: Copy + FromBytes> ConfigReadable<T> for ReadOnly<T> {}
49+
impl<T: Copy + FromBytes + Immutable + IntoBytes> ConfigReadable<T> for ReadWrite<T> {}
50+
impl<T: Copy + FromBytes + Immutable + IntoBytes> ConfigWritable<T> for ReadWrite<T> {}
51+
impl<T: Copy + Immutable + IntoBytes> ConfigWritable<T> for WriteOnly<T> {}
52+
53+
/// Wrapper for `Transport::read_config_space`` with an extra dummy parameter to force the correct
54+
/// type to be inferred.
55+
#[inline(always)]
56+
pub(crate) fn read_help<T, V, R>(
57+
transport: &T,
58+
offset: usize,
59+
_dummy_r: Option<R>,
60+
) -> Result<V, Error>
61+
where
62+
T: Transport,
63+
V: FromBytes,
64+
R: ConfigReadable<V>,
65+
{
66+
transport.read_config_space(offset)
67+
}
68+
69+
/// Wrapper for Transport::write_config_space with an extra dummy parameter to force the correct
70+
/// type to be inferred.
71+
#[inline(always)]
72+
pub(crate) fn write_help<T, V, W>(
73+
transport: &mut T,
74+
offset: usize,
75+
value: V,
76+
_dummy_w: Option<W>,
77+
) -> Result<(), Error>
78+
where
79+
T: Transport,
80+
V: Immutable + IntoBytes,
81+
W: ConfigWritable<V>,
82+
{
83+
transport.write_config_space(offset, value)
84+
}
85+
86+
/// Reads the given field of the given struct from the device config space via the given transport.
87+
macro_rules! read_config {
88+
($transport:expr, $struct:ty, $field:ident) => {{
89+
let dummy_struct: Option<$struct> = None;
90+
let dummy_field = dummy_struct.map(|s| s.$field);
91+
crate::config::read_help(
92+
&$transport,
93+
core::mem::offset_of!($struct, $field),
94+
dummy_field,
95+
)
96+
}};
97+
}
98+
99+
/// Writes the given field of the given struct from the device config space via the given transport.
100+
macro_rules! write_config {
101+
($transport:expr, $struct:ty, $field:ident, $value:expr) => {{
102+
let dummy_struct: Option<$struct> = None;
103+
let dummy_field = dummy_struct.map(|s| s.$field);
104+
crate::config::write_help(
105+
&mut $transport,
106+
core::mem::offset_of!($struct, $field),
107+
$value,
108+
dummy_field,
109+
)
110+
}};
111+
}
112+
113+
pub(crate) use read_config;
114+
pub(crate) use write_config;

0 commit comments

Comments
 (0)