• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
new(value: T) -> Self13     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.
new(value: T) -> Self25     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.
new(value: T) -> Self37     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)]
read_help<T, V, R>( transport: &T, offset: usize, _dummy_r: Option<R>, ) -> Result<V, Error> where T: Transport, V: FromBytes, R: ConfigReadable<V>,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)]
write_help<T, V, W>( transport: &mut T, offset: usize, value: V, _dummy_w: Option<W>, ) -> Result<(), Error> where T: Transport, V: Immutable + IntoBytes, W: ConfigWritable<V>,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;
115