nvme/ds/identify/
namespace.rs

1use core::{cmp::min, fmt::Debug};
2
3use modular_bitfield::prelude::*;
4
5#[derive(Clone)]
6#[repr(C)]
7pub struct IdentifyNamespaceDataStructure {
8    pub size: u64,
9    pub capacity: u64,
10    pub utilization: u64,
11    pub features: NamespaceFeatures,
12    num_lba_formats: u8,
13    pub formatted_lba_size: FormattedLbaSize,
14    _resv: [u8; 101],
15    lba_format_support: [LbaFormat; 64],
16    _resv2: [u8; 4096 - 384],
17}
18
19impl Default for IdentifyNamespaceDataStructure {
20    fn default() -> Self {
21        Self {
22            size: Default::default(),
23            capacity: Default::default(),
24            utilization: Default::default(),
25            features: Default::default(),
26            num_lba_formats: Default::default(),
27            formatted_lba_size: Default::default(),
28            _resv: [0; 101],
29            lba_format_support: [Default::default(); 64],
30            _resv2: [0; 4096 - 384],
31        }
32    }
33}
34
35impl Debug for IdentifyNamespaceDataStructure {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        f.debug_struct("IdentifyNamespaceDataStructure")
38            .field("size", &self.size)
39            .field("capacity", &self.capacity)
40            .field("utilization", &self.utilization)
41            .field("features", &self.features)
42            .field("num_lba_formats", &self.num_lba_formats)
43            .field("formatted_lba_size", &self.formatted_lba_size)
44            .field("lba_format_support", &self.lba_formats())
45            .finish()
46    }
47}
48
49impl IdentifyNamespaceDataStructure {
50    pub fn lba_formats(&self) -> &[LbaFormat] {
51        &self.lba_format_support[0..=min(self.num_lba_formats.into(), 63)]
52    }
53}
54
55const _SIZE_CHECKER: [u8; 0x1000] = [0; std::mem::size_of::<IdentifyNamespaceDataStructure>()];
56
57#[bitfield(bits = 32)]
58#[derive(Default, Clone, Debug, Copy)]
59pub struct LbaFormat {
60    #[skip(setters)]
61    pub metadata_size: u16,
62    #[skip(setters)]
63    pub data_size_log2: u8,
64    #[skip(setters)]
65    pub relative_performance: RelativePerformance,
66    #[skip]
67    res: B6,
68}
69
70impl LbaFormat {
71    pub fn data_size(&self) -> usize {
72        1 << self.data_size_log2()
73    }
74}
75
76#[derive(Specifier, Clone, Debug)]
77#[bits = 2]
78pub enum RelativePerformance {
79    Best = 0,
80    Better = 1,
81    Good = 2,
82    Degraded = 3,
83}
84
85#[bitfield(bits = 8)]
86#[derive(Debug, Default, Clone)]
87pub struct FormattedLbaSize {
88    #[skip(setters)]
89    idx_lo: B4,
90    #[skip(setters)]
91    pub extended_block: B1,
92    #[skip(setters)]
93    idx_hi: B2,
94    #[skip]
95    resv: B1,
96}
97
98impl FormattedLbaSize {
99    pub fn index(&self) -> usize {
100        usize::from(self.idx_lo()) | usize::from(self.idx_hi()) << 4
101    }
102}
103
104#[bitfield(bits = 8)]
105#[derive(Debug, Default, Clone)]
106pub struct NamespaceFeatures {
107    #[skip(setters)]
108    pub supports_thin_provisioning: B1,
109    #[skip(setters)]
110    pub supports_atomic_fields: B1,
111    #[skip(setters)]
112    pub supports_dealloc_lb_err: B1,
113    #[skip(setters)]
114    pub uid_reuse: B1,
115    #[skip(setters)]
116    pub opt_perf: B1,
117    #[skip]
118    resv: B3,
119}