1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
use modular_bitfield::prelude::*;

use crate::ds::{Microseconds, Minutes, OneHundredMilliseconds, Seconds};

#[derive(Clone, Debug)]
#[repr(C)]
pub struct IdentifyControllerDataStructure {
    pub vendor: u16,
    pub subsystem_vendor_id: u16,
    pub serial_number: [u8; 20],
    pub model_number: [u8; 40],
    pub firmware_revision: u64,
    pub reccommended_arbitration_burst: u8,
    pub ieee_oui_identifier: [u8; 3],
    pub multipath_io_and_namespace_sharing_caps: MultipathIONamespaceSharingCaps,
    pub max_data_transfer_size: u8,
    pub controller_id: u16,
    pub version: u32,
    pub rtd3_resume_latency: Microseconds,
    pub rtd3_entry_latency: Microseconds,
    pub optional_async_events_supported: OptionalAsyncEventsSupported,
    pub controller_attributes: ControllerAttributes,
    pub read_recovery_levels_supported: ReadRecoveryLevelsSupported,
    pub res0: [u8; 9],
    pub controller_type: ControllerType,
    pub fru_globally_unique_identifier: u128,
    pub command_retry_delay_time_1: OneHundredMilliseconds,
    pub command_retry_delay_time_2: OneHundredMilliseconds,
    pub command_retry_delay_time_3: OneHundredMilliseconds,
    pub res1: [u8; 106],
    pub res2: [u8; 13],
    pub nvm_subsystem_report: NvmSubsystemReport,
    pub vpd_write_cycle_info: VPDWriteCycleInfo,
    pub management_endpoint_capabilities: ManagementEndpointCapabilities,
    pub optional_admin_command_support: OptionalAdminCommandSupport,
    pub abort_command_limit: u8,
    pub async_event_request_limit: u8,
    pub firmware_updates: FirmwareUpdates,
    pub log_page_attributes: LogPageAttributes,
    pub error_log_page_entries: u8,
    pub nr_power_states_support: u8,
    pub admin_vendor_specific_command_config: u8,
    pub autonomous_power_state_transition_attributes: u8,
    pub warning_composite_temp_threshold: u16,
    pub critical_composite_temp_threshold: u16,
    pub max_time_for_firmware_activation: OneHundredMilliseconds,
    pub host_memory_buffer_preferred_size: u32,
    pub host_memory_buffer_minimum_size: u32,
    pub total_nvm_capacity: u128,
    pub unallocated_nvm_capacity: u128,
    pub replay_protected_memory_block_support: ReplayProtectedMemoryBlockSupport,
    pub extended_device_self_test_time: Minutes,
    pub device_self_test_options: u8,
    pub firmware_upgrade_granularity: u8,
    pub keep_alive_support: OneHundredMilliseconds,
    pub host_controlled_thermal_management_attributes: u16,
    pub min_thermal_management_temp: u16,
    pub max_thermal_management_temp: u16,
    pub sanitize_capabilities: SanitizeCapabilities,
    pub host_memory_buffer_min_desc_entry_size: u32,
    pub host_memory_buffer_max_desc_entries: u16,
    pub nvm_set_ident_maximum: u16,
    pub endurance_group_ident_maximum: u16,
    pub ana_transition_time: Seconds,
    _res_todo: [u8; 3750],
}

impl Default for IdentifyControllerDataStructure {
    fn default() -> Self {
        Self {
            vendor: Default::default(),
            subsystem_vendor_id: Default::default(),
            serial_number: Default::default(),
            model_number: [0; 40],
            firmware_revision: Default::default(),
            reccommended_arbitration_burst: Default::default(),
            ieee_oui_identifier: Default::default(),
            multipath_io_and_namespace_sharing_caps: Default::default(),
            max_data_transfer_size: Default::default(),
            controller_id: Default::default(),
            version: Default::default(),
            rtd3_resume_latency: Default::default(),
            rtd3_entry_latency: Default::default(),
            optional_async_events_supported: Default::default(),
            controller_attributes: Default::default(),
            read_recovery_levels_supported: Default::default(),
            res0: Default::default(),
            controller_type: ControllerType::IOController,
            fru_globally_unique_identifier: Default::default(),
            command_retry_delay_time_1: Default::default(),
            command_retry_delay_time_2: Default::default(),
            command_retry_delay_time_3: Default::default(),
            res1: [0; 106],
            res2: Default::default(),
            nvm_subsystem_report: Default::default(),
            vpd_write_cycle_info: Default::default(),
            management_endpoint_capabilities: Default::default(),
            optional_admin_command_support: Default::default(),
            abort_command_limit: Default::default(),
            async_event_request_limit: Default::default(),
            firmware_updates: Default::default(),
            log_page_attributes: Default::default(),
            error_log_page_entries: Default::default(),
            nr_power_states_support: Default::default(),
            admin_vendor_specific_command_config: Default::default(),
            autonomous_power_state_transition_attributes: Default::default(),
            warning_composite_temp_threshold: Default::default(),
            critical_composite_temp_threshold: Default::default(),
            max_time_for_firmware_activation: Default::default(),
            host_memory_buffer_preferred_size: Default::default(),
            host_memory_buffer_minimum_size: Default::default(),
            total_nvm_capacity: Default::default(),
            unallocated_nvm_capacity: Default::default(),
            replay_protected_memory_block_support: Default::default(),
            extended_device_self_test_time: Default::default(),
            device_self_test_options: Default::default(),
            firmware_upgrade_granularity: Default::default(),
            keep_alive_support: Default::default(),
            host_controlled_thermal_management_attributes: Default::default(),
            min_thermal_management_temp: Default::default(),
            max_thermal_management_temp: Default::default(),
            sanitize_capabilities: Default::default(),
            host_memory_buffer_min_desc_entry_size: Default::default(),
            host_memory_buffer_max_desc_entries: Default::default(),
            nvm_set_ident_maximum: Default::default(),
            endurance_group_ident_maximum: Default::default(),
            ana_transition_time: Default::default(),
            _res_todo: [0; 3750],
        }
    }
}

#[cfg(not(target_arch = "aarch64"))]
const _SIZE_CHECKER: [u8; 0x1000] = [0; std::mem::size_of::<IdentifyControllerDataStructure>()];

#[bitfield(bits = 8)]
#[derive(Default, Clone, Debug)]
pub struct MultipathIONamespaceSharingCaps {
    #[skip(setters)]
    pub nvm_sub_multiple: B1,
    #[skip(setters)]
    pub nvm_sub_two_or_more: B1,
    #[skip(setters)]
    pub sriov_controller: B1,
    #[skip(setters)]
    pub asym_namespace_access_reporting: B1,
    #[skip]
    res: B4,
}

#[bitfield(bits = 32)]
#[derive(Default, Clone, Debug)]
pub struct OptionalAsyncEventsSupported {
    #[skip]
    res: B8,
    #[skip(setters)]
    pub namespace_attribute_notices: B1,
    #[skip(setters)]
    pub firmware_activation_notices: B1,
    #[skip]
    res1: B1,
    #[skip(setters)]
    pub asym_namespace_access_change: B1,
    #[skip(setters)]
    pub predictable_latency_event_aggregate_log: B1,
    #[skip(setters)]
    pub lba_status_info_alert: B1,
    #[skip(setters)]
    pub endurance_group_event_aggregate_log: B1,
    #[skip(setters)]
    pub normal_nvm_subsystem_shutdown: B1,
    #[skip]
    res2: B11,
    #[skip(setters)]
    pub zone_desc_changed_notices: B1,
    #[skip]
    res3: B3,
    #[skip(setters)]
    pub discovery_log_page_change: B1,
}

#[bitfield(bits = 32)]
#[derive(Default, Clone, Debug)]
pub struct ControllerAttributes {
    #[skip(setters)]
    pub host_id: B1,
    #[skip(setters)]
    pub non_op_power_state_permissive_mode: B1,
    #[skip(setters)]
    pub nvm_sets: B1,
    #[skip(setters)]
    pub read_recovery_levels: B1,
    #[skip(setters)]
    pub endurance_groups: B1,
    #[skip(setters)]
    pub predictable_latency_mode: B1,
    #[skip(setters)]
    pub traffic_based_keep_alive: B1,
    #[skip(setters)]
    pub namespace_granularity: B1,
    #[skip(setters)]
    pub sq_associations: B1,
    #[skip(setters)]
    pub uuid_list: B1,
    #[skip(setters)]
    pub multi_domain_subsystem: B1,
    #[skip(setters)]
    pub fixed_domain_capacity_management: B1,
    #[skip(setters)]
    pub variable_capacity_management: B1,
    #[skip(setters)]
    pub delete_endurance_group: B1,
    #[skip(setters)]
    pub delete_nvm_set: B1,
    #[skip(setters)]
    pub extended_lba_formats_supported: B1,
    #[skip]
    res: B16,
}

#[derive(Default, Clone, Debug)]
pub struct ReadRecoveryLevelsSupported(u16);

#[derive(Clone, Debug)]
#[repr(u8)]
pub enum ControllerType {
    NotReported,
    IOController,
    DiscoveryController,
    AdministrativeController,
}

#[bitfield(bits = 8)]
#[derive(Default, Clone, Debug)]
pub struct NvmSubsystemReport {
    #[skip(setters)]
    pub nvme_storage_device: B1,
    #[skip(setters)]
    pub nvme_enclosure: B1,
    #[skip]
    res: B6,
}

#[bitfield(bits = 8)]
#[derive(Default, Clone, Debug)]
pub struct VPDWriteCycleInfo {
    #[skip(setters)]
    pub write_cycles_remaining: B7,
    #[skip(setters)]
    pub valid: B1,
}

#[bitfield(bits = 8)]
#[derive(Default, Clone, Debug)]
pub struct ManagementEndpointCapabilities {
    #[skip]
    pub res: B6,
    #[skip(setters)]
    pub pcie_management_endpoint: B1,
    #[skip(setters)]
    pub smbus_port_management_endpoint: B1,
}

#[bitfield(bits = 16)]
#[derive(Default, Clone, Debug)]
pub struct OptionalAdminCommandSupport {
    #[skip(setters)]
    pub security_send_and_recv: B1,
    #[skip(setters)]
    pub format_nvm: B1,
    #[skip(setters)]
    pub firmware_download_and_commit: B1,
    #[skip(setters)]
    pub namespace_management: B1,
    #[skip(setters)]
    pub device_self_test: B1,
    #[skip(setters)]
    pub directives: B1,
    #[skip(setters)]
    pub nvme_mi_send_and_recv: B1,
    #[skip(setters)]
    pub virtualization_management: B1,
    #[skip(setters)]
    pub doorbell_buffer_config: B1,
    #[skip(setters)]
    pub get_lba_status: B1,
    #[skip(setters)]
    pub command_and_feature_lockdown: B1,
    #[skip]
    res: B5,
}

#[bitfield(bits = 8)]
#[derive(Default, Clone, Debug)]
pub struct FirmwareUpdates {
    #[skip(setters)]
    pub first_firmware_slot_readonly: B1,
    #[skip(setters)]
    pub number_of_firmware_slots: B3,
    #[skip(setters)]
    pub firmware_activation_without_reset: B1,
    #[skip(setters)]
    pub support_multiple_update_detection: B1,
    #[skip]
    res: B2,
}

#[bitfield(bits = 8)]
#[derive(Default, Clone, Debug)]
pub struct LogPageAttributes {
    #[skip(setters)]
    pub per_namespace_smart_log: B1,
    #[skip(setters)]
    pub commands_supported_and_effects: B1,
    #[skip(setters)]
    pub get_log_page: B1,
    #[skip(setters)]
    pub telemetry_host_initiated: B1,
    #[skip(setters)]
    pub persistent_event_log: B1,
    #[skip(setters)]
    pub supported_effects_features_and_nvme_mi: B1,
    #[skip(setters)]
    pub data_area_4: B1,
    #[skip]
    res: B1,
}

#[bitfield(bits = 32)]
#[derive(Default, Clone, Debug)]
pub struct ReplayProtectedMemoryBlockSupport {
    #[skip(setters)]
    pub nr_rpmb_units: B3,
    #[skip(setters)]
    pub auth_method: AuthMethod,
    #[skip]
    res: B10,
    #[skip(setters)]
    pub total_size: B8,
    #[skip(setters)]
    pub access_size: B8,
}

#[derive(BitfieldSpecifier, Clone, Debug)]
#[bits = 3]
pub enum AuthMethod {
    HmacSha256,
}

#[bitfield(bits = 32)]
#[derive(Default, Clone, Debug)]
pub struct SanitizeCapabilities {
    #[skip(setters)]
    pub crypto_erase: B1,
    #[skip(setters)]
    pub block_erase: B1,
    #[skip(setters)]
    pub overwrite: B1,
    #[skip]
    res: B26,
    #[skip(setters)]
    pub no_dealloc_inhibited: B1,
    #[skip(setters)]
    pub no_dealloc_mods_media: B2,
}