pcics/extended_capabilities/
address_translation_services.rs

1/*!
2# Address Translation Services (ATS)
3
4ATS extends the PCIe protocol to support an address translation agent (TA) that
5translates DMA addresses to cached addresses in the device.
6
7## Struct diagram
8[AddressTranslationServices]
9- [AtsCapability]
10- [AtsControl]
11
12## Examples
13
14```rust
15# use pcics::extended_capabilities::address_translation_services::*;
16let data = [
17    0x0f, 0x00, 0x00, 0x00, 0x24, 0x00, 0x02, 0x00,
18];
19let result = data[4..].try_into().unwrap();
20let sample = AddressTranslationServices {
21    ats_capability: AtsCapability {
22        invalidate_queue_depth: 4,
23        page_aligned_request: true,
24        global_invalidate_supported: false,
25    },
26    ats_control: AtsControl {
27        smallest_translation_unit: 2,
28        enable: false,
29    }
30};
31assert_eq!(sample, result);
32```
33*/
34
35use heterob::{bit_numbering::Lsb, endianness::Le, Seq, P2, P3, P4};
36
37use super::ExtendedCapabilityDataError;
38
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct AddressTranslationServices {
41    /// ATS Capability
42    pub ats_capability: AtsCapability,
43    /// ATS Control
44    pub ats_control: AtsControl,
45}
46impl TryFrom<&[u8]> for AddressTranslationServices {
47    type Error = ExtendedCapabilityDataError;
48
49    fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
50        let Seq {
51            head: Le((ats_capability, ats_control)),
52            ..
53        } = P2(slice)
54            .try_into()
55            .map_err(|_| ExtendedCapabilityDataError {
56                name: "Address Translation Services",
57                size: 4,
58            })?;
59        Ok(Self {
60            ats_capability: From::<u16>::from(ats_capability),
61            ats_control: From::<u16>::from(ats_control),
62        })
63    }
64}
65
66/// ATS Capability
67#[derive(Debug, Clone, PartialEq, Eq)]
68pub struct AtsCapability {
69    /// Invalidate Queue Depth
70    pub invalidate_queue_depth: u8,
71    /// Page Aligned Request
72    pub page_aligned_request: bool,
73    /// Global Invalidate Supported
74    pub global_invalidate_supported: bool,
75}
76
77impl From<u16> for AtsCapability {
78    fn from(word: u16) -> Self {
79        let Lsb((invalidate_queue_depth, page_aligned_request, global_invalidate_supported, ())) =
80            P4::<_, 5, 1, 1, 9>(word).into();
81        Self {
82            invalidate_queue_depth,
83            page_aligned_request,
84            global_invalidate_supported,
85        }
86    }
87}
88
89#[derive(Debug, Clone, PartialEq, Eq)]
90pub struct AtsControl {
91    /// Smallest Translation Unit (STU)
92    pub smallest_translation_unit: u8,
93    /// Enable (E)
94    pub enable: bool,
95}
96
97impl From<u16> for AtsControl {
98    fn from(word: u16) -> Self {
99        let Lsb((smallest_translation_unit, (), enable)) = P3::<_, 5, 10, 1>(word).into();
100        Self {
101            smallest_translation_unit,
102            enable,
103        }
104    }
105}