1#[macro_export]
7macro_rules! pci_bit_field {
8 (
9 $(
10 $(#[$attr:meta])*
11 $vis:vis struct $name:ident<$lifetime:lifetime> : $mode:ident $type:ty {
12 $(
13 $(#[$elem_attr:meta])*
14 $elem_name:ident @ $elem_first_bit:literal$(--$elem_last_bit:literal)? :
15 $elem_mode:ident $($elem_type:ty)?
16 ),* $(,)?
17 }
18 )*
19 ) => {
20 $(
21 $(#[$attr])*
22 #[derive(Clone, Copy)]
23 $vis struct $name<$lifetime> {
24 region: &$lifetime dyn $crate::regions::PciRegion,
25 offset: u64,
26 }
27
28 impl<'a> $crate::regions::BackedByPciSubregion<'a> for $name<'a> {
29 fn backed_by(as_subregion: impl $crate::regions::AsPciSubregion<'a>) -> Self {
30 let subregion = $crate::regions::AsPciSubregion::as_subregion(&as_subregion);
31 $name {
32 region: subregion.underlying_region(),
33 offset: subregion.offset_in_underlying_region(),
34 }
35 }
36 }
37
38 impl<'a> $crate::regions::AsPciSubregion<'a> for $name<'a> {
39 fn as_subregion(&self) -> $crate::regions::PciSubregion<'a> {
40 self.region
41 .subregion(self.offset..self.offset + ::std::mem::size_of::<$type>() as u64)
42 }
43 }
44
45 impl $crate::regions::structured::PciBitFieldReadable for $name<'_> {
46 type Type = $type;
47
48 fn read(&self) -> ::std::io::Result<$type> {
49 $crate::regions::structured::PciRegisterValue::read(
50 self.region,
51 self.offset,
52 )
53 }
54 }
55
56 impl ::std::fmt::Debug for $name<'_> {
57 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
58 let mut debug_struct = f.debug_struct(::std::stringify!($name));
59 $(
60 $crate::_pci_bit_field_debug_elem!(
61 self, debug_struct, $elem_name : $elem_mode $($elem_type)?
62 );
63 )*
64 debug_struct.finish()
65 }
66 }
67
68 impl<$lifetime> $name<$lifetime> {
69 $(
70 $crate::_pci_bit_field_elem! {
71 $lifetime $type :
72 $(#[$elem_attr])*
73 $elem_name @ $elem_first_bit$(--$elem_last_bit)? :
74 $elem_mode $($elem_type)?
75 }
76 )*
77 }
78
79 $crate::_pci_bit_field_impl_writeable_part! {
80 impl $name<$lifetime> : $mode $type {
81 $(
82 $(#[$elem_attr])*
83 $elem_name @ $elem_first_bit$(--$elem_last_bit)? :
84 $elem_mode $($elem_type)?
85 ),*
86 }
87 }
88 )*
89 };
90}
91
92#[doc(hidden)]
94#[macro_export]
95macro_rules! _pci_bit_field_debug_elem {
96 ( $self:ident, $debug_struct:ident, $elem_name:ident : RsvdP ) => {};
97 ( $self:ident, $debug_struct:ident, $elem_name:ident : RsvdZ ) => {};
98 ( $self:ident, $debug_struct:ident, $elem_name:ident : $elem_mode:ident $($elem_type:ty)? ) => {
99 $debug_struct.field(::std::stringify!($elem_name), &$self.$elem_name())
100 };
101}
102
103#[doc(hidden)]
105#[macro_export]
106macro_rules! _pci_bit_field_impl_writeable_part {
107 (
108 impl $name:ident<$lifetime:lifetime> : RO $type:ty {
109 $(
110 $(#[$elem_attr:meta])*
111 $elem_name:ident @ $elem_first_bit:literal$(--$elem_last_bit:literal)? :
112 $elem_mode:ident $($elem_type:ty)?
113 ),* $(,)?
114 }
115 ) => {};
116
117 (
118 impl $name:ident<$lifetime:lifetime> : RW $type:ty {
119 $(
120 $(#[$elem_attr:meta])*
121 $elem_name:ident @ $elem_first_bit:literal$(--$elem_last_bit:literal)? :
122 $elem_mode:ident $($elem_type:ty)?
123 ),* $(,)?
124 }
125 ) => {
126 impl $crate::regions::structured::PciBitFieldWriteable for $name<'_> {
127 const WRITE_MASK: $type = $crate::_pci_bit_field_write_mask!(
128 $type,
129 $(
130 @ $elem_first_bit$(--$elem_last_bit)? :
131 $elem_mode $($elem_type)?
132 ),*
133 );
134
135 fn write(&self, value: $type) -> ::std::io::Result<()> {
136 $crate::regions::structured::PciRegisterValue::write(
137 value,
138 self.region,
139 self.offset,
140 )
141 }
142 }
143 }
144}
145
146#[doc(hidden)]
148#[macro_export]
149macro_rules! _pci_bit_field_elem {
150 (
151 $lifetime:lifetime $field_type:ty :
152 $(#[$elem_attr:meta])*
153 $elem_name:ident @ $elem_bit:literal : RO
154 ) => {
155 $(#[$elem_attr])*
156 pub fn $elem_name(&self) -> $crate::regions::structured::PciBitReadOnly<$lifetime, $field_type> {
157 $crate::regions::structured::PciBitReadOnly::backed_by(
158 self.region,
159 self.offset,
160 1 << $elem_bit, )
162 }
163 };
164
165 (
166 $lifetime:lifetime $field_type:ty :
167 $(#[$elem_attr:meta])*
168 $elem_name:ident @ $elem_first_bit:literal--$elem_last_bit:literal : RO $elem_type:ty
169 ) => {
170 $(#[$elem_attr])*
171 pub fn $elem_name(&self) -> $crate::regions::structured::PciBitsReadOnly<$lifetime, $field_type, $elem_type> {
172 const MASK: $field_type = $crate::_bit_range!($field_type, $elem_first_bit, $elem_last_bit);
173 $crate::regions::structured::PciBitsReadOnly::backed_by(
174 self.region,
175 self.offset,
176 MASK,
177 $elem_first_bit, )
179 }
180 };
181
182 (
183 $lifetime:lifetime $field_type:ty :
184 $(#[$elem_attr:meta])*
185 $elem_name:ident @ $elem_bit:literal : RW
186 ) => {
187 $(#[$elem_attr])*
188 pub fn $elem_name(&self) -> $crate::regions::structured::PciBitReadWrite<$lifetime, $field_type> {
189 $crate::regions::structured::PciBitReadWrite::backed_by(
190 self.region,
191 self.offset,
192 1 << $elem_bit, <Self as $crate::regions::structured::PciBitFieldWriteable>::WRITE_MASK,
194 )
195 }
196 };
197
198 (
199 $lifetime:lifetime $field_type:ty :
200 $(#[$elem_attr:meta])*
201 $elem_name:ident @ $elem_first_bit:literal--$elem_last_bit:literal : RW $elem_type:ty
202 ) => {
203 $(#[$elem_attr])*
204 pub fn $elem_name(&self) -> $crate::regions::structured::PciBitsReadWrite<$lifetime, $field_type, $elem_type> {
205 const MASK: $field_type = $crate::_bit_range!($field_type, $elem_first_bit, $elem_last_bit);
206 $crate::regions::structured::PciBitsReadWrite::backed_by(
207 self.region,
208 self.offset,
209 MASK,
210 $elem_first_bit, <Self as $crate::regions::structured::PciBitFieldWriteable>::WRITE_MASK
212 )
213 }
214 };
215
216 (
217 $lifetime:lifetime $field_type:ty :
218 $(#[$elem_attr:meta])*
219 $elem_name:ident @ $elem_bit:literal : RW1C
220 ) => {
221 $(#[$elem_attr])*
222 pub fn $elem_name(&self) -> $crate::regions::structured::PciBitReadClear<$lifetime, $field_type> {
223 $crate::regions::structured::PciBitReadClear::backed_by(
224 self.region,
225 self.offset,
226 1 << $elem_bit, <Self as $crate::regions::structured::PciBitFieldWriteable>::WRITE_MASK,
228 )
229 }
230 };
231
232 (
233 $lifetime:lifetime $field_type:ty :
234 $elem_name:ident @ $elem_bit:literal : RsvdP
235 ) => {};
236
237 (
238 $lifetime:lifetime $field_type:ty :
239 $elem_name:ident @ $elem_first_bit:literal--$elem_last_bit:literal : RsvdP
240 ) => {};
241
242 (
243 $lifetime:lifetime $field_type:ty :
244 $elem_name:ident @ $elem_bit:literal : RsvdZ
245 ) => {};
246
247 (
248 $lifetime:lifetime $field_type:ty :
249 $elem_name:ident @ $elem_first_bit:literal--$elem_last_bit:literal : RsvdZ
250 ) => {};
251}
252
253#[doc(hidden)]
255#[macro_export]
256macro_rules! _pci_bit_field_write_mask {
257 (
258 $field_type:ty,
259 $(
260 @ $elem_first_bit:literal$(--$elem_last_bit:literal)? :
261 $elem_mode:ident $($elem_type:ty)?
262 ),* $(,)?
263 ) => {
264 $(
265 $crate::_pci_bit_field_write_mask_elem!(
266 $field_type,
267 @ $elem_first_bit$(--$elem_last_bit)? :
268 $elem_mode $($elem_type)?
269 ) &
270 )* !0
271 };
272}
273
274#[doc(hidden)]
276#[macro_export]
277macro_rules! _pci_bit_field_write_mask_elem {
278 ($field_type:ty, @ $elem_bit:literal : RW1C) => {{
279 !(1 << $elem_bit)
280 }};
281
282 ($field_type:ty, @ $elem_bit:literal : RsvdZ) => {{
283 !(1 << $elem_bit)
284 }};
285
286 ($field_type:ty, @ $elem_first_bit:literal--$elem_last_bit:literal : RsvdZ) => {{
287 !$crate::_bit_range!($field_type, $elem_first_bit, $elem_last_bit)
288 }};
289
290 (
291 $field_type:ty,
292 @ $elem_first_bit:literal$(--$elem_last_bit:literal)? :
293 $elem_mode:ident $($elem_type:ty)?
294 ) => {{
295 !0
296 }};
297}
298
299#[doc(hidden)]
301#[macro_export]
302macro_rules! _bit_range {
303 ($field_type:ty, $elem_first_bit:literal, $elem_last_bit:literal) => {{
304 let one: $field_type = 1;
305 let mask_1 = match one.checked_shl($elem_last_bit + 1) {
306 ::std::option::Option::Some(v) => v - 1,
307 ::std::option::Option::None => !0,
308 };
309 let mask_2 = (1 << $elem_first_bit) - 1;
310 mask_1 & !mask_2
311 }};
312}
313
314#[cfg(test)]
317mod tests {
318 #[test]
319 fn test_pci_bit_field_write_mask() {
320 assert_eq!(
321 _pci_bit_field_write_mask!(
322 u8,
323 @ 3 : RsvdZ,
324 @ 6--7 : RsvdZ,
325 ),
326 0b_0011_0111_u8
327 );
328 }
329
330 #[test]
331 fn test_pci_bit_field_write_mask_elem() {
332 assert_eq!(
333 _pci_bit_field_write_mask_elem!(u8, @ 0 : RsvdZ),
334 0b_1111_1110_u8
335 );
336 assert_eq!(
337 _pci_bit_field_write_mask_elem!(u8, @ 3 : RsvdZ),
338 0b_1111_0111_u8
339 );
340 assert_eq!(
341 _pci_bit_field_write_mask_elem!(u8, @ 7 : RsvdZ),
342 0b_0111_1111_u8
343 );
344
345 assert_eq!(
346 _pci_bit_field_write_mask_elem!(u8, @ 0--1 : RsvdZ),
347 0b_1111_1100_u8
348 );
349 assert_eq!(
350 _pci_bit_field_write_mask_elem!(u8, @ 3--5 : RsvdZ),
351 0b_1100_0111_u8
352 );
353 assert_eq!(
354 _pci_bit_field_write_mask_elem!(u8, @ 6--7 : RsvdZ),
355 0b_0011_1111_u8
356 );
357 }
358}
359
360