nvme/ds/identify/
namespace.rs

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