pci_core/capabilities/
pci_express.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! PCI Express Capability with Function Level Reset (FLR) support.
5
6use super::PciCapability;
7use crate::spec::caps::CapabilityId;
8use crate::spec::caps::pci_express;
9use crate::spec::caps::pci_express::{
10    LinkSpeed, LinkWidth, PciExpressCapabilityHeader, SupportedLinkSpeedsVector,
11};
12use inspect::Inspect;
13use parking_lot::Mutex;
14use std::sync::Arc;
15
16/// FLR bit is the 28th bit in the Device Capabilities register (0 indexed).
17pub const PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK: u32 = 1 << 28;
18
19/// Callback interface for handling Function Level Reset (FLR) events.
20pub trait FlrHandler: Send + Sync + Inspect {
21    /// Called when Function Level Reset is initiated.
22    fn initiate_flr(&self);
23}
24
25#[derive(Debug, Inspect)]
26struct PciExpressState {
27    device_control: pci_express::DeviceControl,
28    device_status: pci_express::DeviceStatus,
29    link_control: pci_express::LinkControl,
30    link_status: pci_express::LinkStatus,
31    slot_control: pci_express::SlotControl,
32    slot_status: pci_express::SlotStatus,
33    root_control: pci_express::RootControl,
34    root_status: pci_express::RootStatus,
35    device_control_2: pci_express::DeviceControl2,
36    device_status_2: pci_express::DeviceStatus2,
37    link_control_2: pci_express::LinkControl2,
38    link_status_2: pci_express::LinkStatus2,
39    slot_control_2: pci_express::SlotControl2,
40    slot_status_2: pci_express::SlotStatus2,
41}
42
43impl PciExpressState {
44    fn new() -> Self {
45        Self {
46            device_control: pci_express::DeviceControl::new(),
47            device_status: pci_express::DeviceStatus::new(),
48            link_control: pci_express::LinkControl::new(),
49            link_status: pci_express::LinkStatus::new()
50                .with_current_link_speed(LinkSpeed::Speed32_0GtS.into_bits() as u16)
51                .with_negotiated_link_width(LinkWidth::X16.into_bits() as u16),
52            slot_control: pci_express::SlotControl::new(),
53            slot_status: pci_express::SlotStatus::new(),
54            root_control: pci_express::RootControl::new(),
55            root_status: pci_express::RootStatus::new(),
56            device_control_2: pci_express::DeviceControl2::new(),
57            device_status_2: pci_express::DeviceStatus2::new(),
58            link_control_2: pci_express::LinkControl2::new()
59                .with_target_link_speed(LinkSpeed::Speed32_0GtS.into_bits() as u16),
60            link_status_2: pci_express::LinkStatus2::new(),
61            slot_control_2: pci_express::SlotControl2::new(),
62            slot_status_2: pci_express::SlotStatus2::new(),
63        }
64    }
65}
66
67#[derive(Inspect)]
68/// Configurable PCI Express capability.
69pub struct PciExpressCapability {
70    pcie_capabilities: pci_express::PciExpressCapabilities,
71    device_capabilities: pci_express::DeviceCapabilities,
72    link_capabilities: pci_express::LinkCapabilities,
73    slot_capabilities: pci_express::SlotCapabilities,
74    root_capabilities: pci_express::RootCapabilities,
75    device_capabilities_2: pci_express::DeviceCapabilities2,
76    link_capabilities_2: pci_express::LinkCapabilities2,
77    slot_capabilities_2: pci_express::SlotCapabilities2,
78    state: Arc<Mutex<PciExpressState>>,
79    #[inspect(skip)]
80    flr_handler: Option<Arc<dyn FlrHandler>>,
81}
82
83impl PciExpressCapability {
84    /// Creates a new PCI Express capability with FLR support.
85    ///
86    /// # Arguments
87    /// * `typ` - The spec-defined device or port type.
88    /// * `flr_handler` - Optional handler to be called when FLR is initiated. This emulator will report that FLR is supported if flr_handler = Some(_)
89    pub fn new(typ: pci_express::DevicePortType, flr_handler: Option<Arc<dyn FlrHandler>>) -> Self {
90        Self {
91            pcie_capabilities: pci_express::PciExpressCapabilities::new()
92                .with_capability_version(2)
93                .with_device_port_type(typ),
94            device_capabilities: pci_express::DeviceCapabilities::new()
95                .with_function_level_reset(flr_handler.is_some()),
96            link_capabilities: pci_express::LinkCapabilities::new()
97                .with_max_link_speed(LinkSpeed::Speed32_0GtS.into_bits()) // PCIe 32.0 GT/s speed
98                .with_max_link_width(LinkWidth::X16.into_bits()), // x16 link width
99            slot_capabilities: pci_express::SlotCapabilities::new(),
100            root_capabilities: pci_express::RootCapabilities::new(),
101            device_capabilities_2: pci_express::DeviceCapabilities2::new(),
102            link_capabilities_2: pci_express::LinkCapabilities2::new()
103                .with_supported_link_speeds_vector(SupportedLinkSpeedsVector::UpToGen5.into_bits()), // Support speeds up to PCIe Gen 5 (32.0 GT/s)
104            slot_capabilities_2: pci_express::SlotCapabilities2::new(),
105            state: Arc::new(Mutex::new(PciExpressState::new())),
106            flr_handler,
107        }
108    }
109
110    fn handle_device_control_status_write(&mut self, val: u32) {
111        // Device Control (2 bytes) + Device Status (2 bytes)
112        let new_control = pci_express::DeviceControl::from_bits(val as u16);
113        let mut state = self.state.lock();
114
115        // Check if FLR was initiated
116        let old_flr = state.device_control.initiate_function_level_reset();
117        let new_flr = new_control.initiate_function_level_reset();
118
119        // DEVNOTE: It is "safe" to drop a new FLR request if there is still a previous
120        // FLR request in progress. The PCIe spec indicates that such behavior is undefined,
121        // so we choose to ignore the new FLR request.
122        if new_flr && !old_flr {
123            if let Some(handler) = &self.flr_handler {
124                handler.initiate_flr();
125            }
126        }
127
128        // Update the control register but clear the FLR bit as it's self-clearing
129        state.device_control = new_control.with_initiate_function_level_reset(false);
130
131        // Handle Device Status - most bits are write-1-to-clear
132        let new_status = pci_express::DeviceStatus::from_bits((val >> 16) as u16);
133        let mut current_status = state.device_status;
134
135        // Clear bits that were written as 1 (write-1-to-clear semantics)
136        if new_status.correctable_error_detected() {
137            current_status.set_correctable_error_detected(false);
138        }
139        if new_status.non_fatal_error_detected() {
140            current_status.set_non_fatal_error_detected(false);
141        }
142        if new_status.fatal_error_detected() {
143            current_status.set_fatal_error_detected(false);
144        }
145        if new_status.unsupported_request_detected() {
146            current_status.set_unsupported_request_detected(false);
147        }
148
149        state.device_status = current_status;
150    }
151
152    fn handle_slot_control_status_write(&mut self, val: u32) {
153        // Slot Control (2 bytes) + Slot Status (2 bytes)
154        let new_slot_control = pci_express::SlotControl::from_bits(val as u16);
155        let mut state = self.state.lock();
156
157        // Mask slot control bits based on slot capabilities
158        // Only allow writes to bits that correspond to capabilities that are present
159        let mut masked_control = new_slot_control;
160
161        // If attention button is not present, attention button enable should be read-only (hardwired to 0)
162        if !self.slot_capabilities.attention_button_present() {
163            masked_control.set_attention_button_pressed_enable(false);
164        }
165
166        // If power controller is not present, power controller control should be read-only (hardwired to 0)
167        if !self.slot_capabilities.power_controller_present() {
168            masked_control.set_power_controller_control(false);
169        }
170
171        // If MRL sensor is not present, MRL sensor changed enable should be read-only (hardwired to 0)
172        if !self.slot_capabilities.mrl_sensor_present() {
173            masked_control.set_mrl_sensor_changed_enable(false);
174        }
175
176        // If attention indicator is not present, attention indicator control should be read-only (hardwired to 00b)
177        if !self.slot_capabilities.attention_indicator_present() {
178            masked_control.set_attention_indicator_control(0);
179        }
180
181        // If power indicator is not present, power indicator control should be read-only (hardwired to 00b)
182        if !self.slot_capabilities.power_indicator_present() {
183            masked_control.set_power_indicator_control(0);
184        }
185
186        // If hotplug is not capable, hotplug interrupt enable should be read-only (hardwired to 0)
187        if !self.slot_capabilities.hot_plug_capable() {
188            masked_control.set_hot_plug_interrupt_enable(false);
189        }
190
191        // If electromechanical interlock is not present, interlock control should be read-only (hardwired to 0)
192        if !self.slot_capabilities.electromechanical_interlock_present() {
193            masked_control.set_electromechanical_interlock_control(false);
194        }
195
196        // If no command completed support, command completed interrupt enable should be read-only (hardwired to 0)
197        if self.slot_capabilities.no_command_completed_support() {
198            masked_control.set_command_completed_interrupt_enable(false);
199        }
200
201        state.slot_control = masked_control;
202
203        // Slot Status upper 16 bits - handle RW1C and RO bits properly
204        let new_slot_status = pci_express::SlotStatus::from_bits((val >> 16) as u16);
205        let mut current_slot_status = state.slot_status;
206
207        // RW1C bits: writing 1 clears the bit, writing 0 leaves it unchanged
208        // Clear bits where a 1 was written (RW1C behavior)
209        if new_slot_status.attention_button_pressed() {
210            current_slot_status.set_attention_button_pressed(false);
211        }
212        if new_slot_status.power_fault_detected() {
213            current_slot_status.set_power_fault_detected(false);
214        }
215        if new_slot_status.mrl_sensor_changed() {
216            current_slot_status.set_mrl_sensor_changed(false);
217        }
218        if new_slot_status.presence_detect_changed() {
219            current_slot_status.set_presence_detect_changed(false);
220        }
221        if new_slot_status.command_completed() {
222            current_slot_status.set_command_completed(false);
223        }
224        if new_slot_status.data_link_layer_state_changed() {
225            current_slot_status.set_data_link_layer_state_changed(false);
226        }
227
228        // RO bits (mrl_sensor_state, presence_detect_state, electromechanical_interlock_status)
229        // are not modified - they remain as they were
230
231        state.slot_status = current_slot_status;
232    }
233
234    fn handle_link_control_status_write(&mut self, val: u32) {
235        // Link Control (2 bytes) + Link Status (2 bytes)
236        let new_link_control = pci_express::LinkControl::from_bits(val as u16);
237        let mut state = self.state.lock();
238
239        // Apply the new link control but ensure retrain_link always reads as 0
240        let mut masked_control = new_link_control;
241        masked_control.set_retrain_link(false); // retrain_link always reads as 0
242
243        state.link_control = masked_control;
244        // Link Status upper 16 bits - read-only, ignore any writes
245    }
246
247    fn handle_link_control_2_write(&mut self, val: u32) {
248        // Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
249        let new_link_control_2 = pci_express::LinkControl2::from_bits(val as u16);
250        let mut state = self.state.lock();
251
252        // Validate that target_link_speed doesn't exceed max_link_speed from Link Capabilities
253        let max_speed = self.link_capabilities.max_link_speed();
254        let requested_speed = new_link_control_2.target_link_speed();
255
256        // Clamp the target link speed to not exceed the maximum supported speed
257        let actual_speed = if requested_speed > max_speed as u16 {
258            max_speed as u16
259        } else {
260            requested_speed
261        };
262
263        // Update Link Control 2 with the validated speed
264        state.link_control_2 = new_link_control_2.with_target_link_speed(actual_speed);
265
266        // Update Link Status to reflect the target link speed as current link speed
267        // This simulates the link retraining and speed negotiation completing immediately
268        state.link_status = state.link_status.with_current_link_speed(actual_speed);
269
270        // Link Status 2 upper 16 bits - mostly read-only, so we don't modify it
271    }
272
273    /// Enable hotplug support for this PCIe capability.
274    /// This configures the appropriate registers to support hotpluggable devices.
275    /// Panics if called on device types other than RootPort or DownstreamSwitchPort.
276    ///
277    /// # Arguments
278    /// * `slot_number` - The physical slot number to assign to this hotplug-capable port
279    pub fn with_hotplug_support(mut self, slot_number: u32) -> Self {
280        use pci_express::DevicePortType;
281
282        // Validate that hotplug is only enabled for appropriate port types
283        let port_type = self.pcie_capabilities.device_port_type();
284        match port_type {
285            DevicePortType::RootPort | DevicePortType::DownstreamSwitchPort => {
286                // Valid port types for hotplug support
287            }
288            DevicePortType::Endpoint | DevicePortType::UpstreamSwitchPort => {
289                panic!(
290                    "Hotplug support is not valid for device port type {:?}. \
291                     Only RootPort and DownstreamSwitchPort support hotplug.",
292                    port_type
293                );
294            }
295        }
296
297        // Enable slot implemented in PCIe capabilities when hotplug is enabled
298        self.pcie_capabilities = self.pcie_capabilities.with_slot_implemented(true);
299
300        // Enable hotplug capabilities in slot capabilities register
301        self.slot_capabilities = self
302            .slot_capabilities
303            .with_hot_plug_surprise(true)
304            .with_hot_plug_capable(true)
305            .with_physical_slot_number(slot_number);
306
307        // Enable Data Link Layer Link Active Reporting when hotplug is enabled
308        self.link_capabilities = self
309            .link_capabilities
310            .with_data_link_layer_link_active_reporting(true);
311
312        self
313    }
314
315    /// Set the presence detect state for the slot.
316    /// This method only has effect if the slot is implemented (slot_implemented = true).
317    /// If slot is not implemented, the call is silently ignored, as the spec says
318    /// "If this register is implemented but the Slot Implemented bit is Clear,
319    /// the field behavior of this entire register with the exception of the DLLSC bit is undefined."
320    ///
321    /// # Arguments
322    /// * `present` - true if a device is present in the slot, false if the slot is empty
323    pub fn set_presence_detect_state(&self, present: bool) {
324        if !self.pcie_capabilities.slot_implemented() {
325            // Silently ignore if slot is not implemented
326            return;
327        }
328
329        let mut state = self.state.lock();
330        state.slot_status =
331            state
332                .slot_status
333                .with_presence_detect_state(if present { 1 } else { 0 });
334    }
335}
336
337impl PciCapability for PciExpressCapability {
338    fn label(&self) -> &str {
339        "pci-express"
340    }
341
342    fn capability_id(&self) -> CapabilityId {
343        CapabilityId::PCI_EXPRESS
344    }
345
346    fn len(&self) -> usize {
347        // Implement the full PCI Express Capability structure (PCI Spec, Section 7.5.3):
348        // 0x00: PCIe Capabilities (2 bytes) + Next Pointer (1 byte) + Capability ID (1 byte)
349        // 0x04: Device Capabilities (4 bytes)
350        // 0x08: Device Control (2 bytes) + Device Status (2 bytes)
351        // 0x0C: Link Capabilities (4 bytes)
352        // 0x10: Link Control (2 bytes) + Link Status (2 bytes)
353        // 0x14: Slot Capabilities (4 bytes)
354        // 0x18: Slot Control (2 bytes) + Slot Status (2 bytes)
355        // 0x1C: Root Control (2 bytes) + Root Capabilities (2 bytes)
356        // 0x20: Root Status (4 bytes)
357        // 0x24: Device Capabilities 2 (4 bytes)
358        // 0x28: Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
359        // 0x2C: Link Capabilities 2 (4 bytes)
360        // 0x30: Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
361        // 0x34: Slot Capabilities 2 (4 bytes)
362        // 0x38: Slot Control 2 (2 bytes) + Slot Status 2 (2 bytes)
363        // Total: 60 bytes (0x3C)
364        0x3C
365    }
366
367    fn read_u32(&self, offset: u16) -> u32 {
368        let label = self.label();
369        match PciExpressCapabilityHeader(offset) {
370            PciExpressCapabilityHeader::PCIE_CAPS => {
371                // PCIe Capabilities Register (16 bits) + Next Pointer (8 bits) + Capability ID (8 bits)
372                (self.pcie_capabilities.into_bits() as u32) << 16
373                    | CapabilityId::PCI_EXPRESS.0 as u32
374            }
375            PciExpressCapabilityHeader::DEVICE_CAPS => self.device_capabilities.into_bits(),
376            PciExpressCapabilityHeader::DEVICE_CTL_STS => {
377                let state = self.state.lock();
378                let device_control = state.device_control.into_bits() as u32;
379                let device_status = state.device_status.into_bits() as u32;
380                device_control | (device_status << 16)
381            }
382            PciExpressCapabilityHeader::LINK_CAPS => self.link_capabilities.into_bits(),
383            PciExpressCapabilityHeader::LINK_CTL_STS => {
384                // Link Control (2 bytes) + Link Status (2 bytes)
385                let state = self.state.lock();
386                state.link_control.into_bits() as u32
387                    | ((state.link_status.into_bits() as u32) << 16)
388            }
389            PciExpressCapabilityHeader::SLOT_CAPS => self.slot_capabilities.into_bits(),
390            PciExpressCapabilityHeader::SLOT_CTL_STS => {
391                // Slot Control (2 bytes) + Slot Status (2 bytes)
392                let state = self.state.lock();
393                state.slot_control.into_bits() as u32
394                    | ((state.slot_status.into_bits() as u32) << 16)
395            }
396            PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
397                // Root Control (2 bytes) + Root Capabilities (2 bytes)
398                let state = self.state.lock();
399                state.root_control.into_bits() as u32
400                    | ((self.root_capabilities.into_bits() as u32) << 16)
401            }
402            PciExpressCapabilityHeader::ROOT_STS => {
403                // Root Status (4 bytes)
404                let state = self.state.lock();
405                state.root_status.into_bits()
406            }
407            PciExpressCapabilityHeader::DEVICE_CAPS_2 => self.device_capabilities_2.into_bits(),
408            PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
409                // Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
410                let state = self.state.lock();
411                state.device_control_2.into_bits() as u32
412                    | ((state.device_status_2.into_bits() as u32) << 16)
413            }
414            PciExpressCapabilityHeader::LINK_CAPS_2 => self.link_capabilities_2.into_bits(),
415            PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
416                // Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
417                let state = self.state.lock();
418                state.link_control_2.into_bits() as u32
419                    | ((state.link_status_2.into_bits() as u32) << 16)
420            }
421            PciExpressCapabilityHeader::SLOT_CAPS_2 => self.slot_capabilities_2.into_bits(),
422            PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
423                // Slot Control 2 (2 bytes) + Slot Status 2 (2 bytes)
424                let state = self.state.lock();
425                state.slot_control_2.into_bits() as u32
426                    | ((state.slot_status_2.into_bits() as u32) << 16)
427            }
428            _ => {
429                tracelimit::warn_ratelimited!(
430                    ?label,
431                    offset,
432                    "unhandled pci express capability read"
433                );
434                0
435            }
436        }
437    }
438
439    fn write_u32(&mut self, offset: u16, val: u32) {
440        let label = self.label();
441        match PciExpressCapabilityHeader(offset) {
442            PciExpressCapabilityHeader::PCIE_CAPS => {
443                // PCIe Capabilities register is read-only
444                tracelimit::warn_ratelimited!(
445                    ?label,
446                    offset,
447                    val,
448                    "write to read-only pcie capabilities"
449                );
450            }
451            PciExpressCapabilityHeader::DEVICE_CAPS => {
452                // Device Capabilities register is read-only
453                tracelimit::warn_ratelimited!(
454                    ?label,
455                    offset,
456                    val,
457                    "write to read-only device capabilities"
458                );
459            }
460            PciExpressCapabilityHeader::DEVICE_CTL_STS => {
461                self.handle_device_control_status_write(val);
462            }
463            PciExpressCapabilityHeader::LINK_CAPS => {
464                // Link Capabilities register is read-only
465                tracelimit::warn_ratelimited!(
466                    ?label,
467                    offset,
468                    val,
469                    "write to read-only link capabilities"
470                );
471            }
472            PciExpressCapabilityHeader::LINK_CTL_STS => {
473                self.handle_link_control_status_write(val);
474            }
475            PciExpressCapabilityHeader::SLOT_CAPS => {
476                // Slot Capabilities register is read-only
477                tracelimit::warn_ratelimited!(
478                    ?label,
479                    offset,
480                    val,
481                    "write to read-only slot capabilities"
482                );
483            }
484            PciExpressCapabilityHeader::SLOT_CTL_STS => {
485                self.handle_slot_control_status_write(val);
486            }
487            PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
488                // Root Control (2 bytes) + Root Capabilities (2 bytes)
489                let mut state = self.state.lock();
490                state.root_control = pci_express::RootControl::from_bits(val as u16);
491                // Root Capabilities upper 16 bits are read-only
492            }
493            PciExpressCapabilityHeader::ROOT_STS => {
494                // Root Status (4 bytes) - many bits are write-1-to-clear
495                let mut state = self.state.lock();
496                // For simplicity, we'll allow basic writes for now
497                state.root_status = pci_express::RootStatus::from_bits(val);
498            }
499            PciExpressCapabilityHeader::DEVICE_CAPS_2 => {
500                // Device Capabilities 2 register is read-only
501                tracelimit::warn_ratelimited!(
502                    ?label,
503                    offset,
504                    val,
505                    "write to read-only device capabilities 2"
506                );
507            }
508            PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
509                // Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
510                let mut state = self.state.lock();
511                state.device_control_2 = pci_express::DeviceControl2::from_bits(val as u16);
512                // Device Status 2 upper 16 bits - mostly read-only or write-1-to-clear
513                state.device_status_2 = pci_express::DeviceStatus2::from_bits((val >> 16) as u16);
514            }
515            PciExpressCapabilityHeader::LINK_CAPS_2 => {
516                // Link Capabilities 2 register is read-only
517                tracelimit::warn_ratelimited!(
518                    ?label,
519                    offset,
520                    val,
521                    "write to read-only link capabilities 2"
522                );
523            }
524            PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
525                self.handle_link_control_2_write(val);
526            }
527            PciExpressCapabilityHeader::SLOT_CAPS_2 => {
528                // Slot Capabilities 2 register is read-only
529                tracelimit::warn_ratelimited!(
530                    ?label,
531                    offset,
532                    val,
533                    "write to read-only slot capabilities 2"
534                );
535            }
536            PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
537                // Slot Control 2 (2 bytes) + Slot Status 2 (2 bytes)
538                let mut state = self.state.lock();
539                state.slot_control_2 = pci_express::SlotControl2::from_bits(val as u16);
540                // Slot Status 2 upper 16 bits - mostly read-only or write-1-to-clear
541                state.slot_status_2 = pci_express::SlotStatus2::from_bits((val >> 16) as u16);
542            }
543            _ => {
544                tracelimit::warn_ratelimited!(
545                    ?label,
546                    offset,
547                    val,
548                    "unhandled pci express capability write"
549                );
550            }
551        }
552    }
553
554    fn reset(&mut self) {
555        let mut state = self.state.lock();
556        *state = PciExpressState::new();
557    }
558
559    fn as_pci_express(&self) -> Option<&PciExpressCapability> {
560        Some(self)
561    }
562
563    fn as_pci_express_mut(&mut self) -> Option<&mut PciExpressCapability> {
564        Some(self)
565    }
566}
567
568mod save_restore {
569    use super::*;
570    use vmcore::save_restore::RestoreError;
571    use vmcore::save_restore::SaveError;
572    use vmcore::save_restore::SaveRestore;
573
574    mod state {
575        use mesh::payload::Protobuf;
576        use vmcore::save_restore::SavedStateRoot;
577
578        #[derive(Protobuf, SavedStateRoot)]
579        #[mesh(package = "pci.capabilities.pci_express")]
580        pub struct SavedState {
581            #[mesh(1)]
582            pub device_control: u16,
583            #[mesh(2)]
584            pub device_status: u16,
585            #[mesh(3)]
586            pub flr_handler: u16,
587        }
588    }
589
590    impl SaveRestore for PciExpressCapability {
591        type SavedState = state::SavedState;
592
593        fn save(&mut self) -> Result<Self::SavedState, SaveError> {
594            Err(SaveError::NotSupported)
595        }
596
597        fn restore(&mut self, _: Self::SavedState) -> Result<(), RestoreError> {
598            Err(RestoreError::SavedStateNotSupported)
599        }
600    }
601}
602
603#[cfg(test)]
604mod tests {
605    use super::*;
606    use crate::spec::caps::pci_express::DevicePortType;
607    use std::sync::atomic::{AtomicBool, Ordering};
608
609    #[derive(Debug)]
610    struct TestFlrHandler {
611        flr_initiated: AtomicBool,
612    }
613
614    impl TestFlrHandler {
615        fn new() -> Arc<Self> {
616            Arc::new(Self {
617                flr_initiated: AtomicBool::new(false),
618            })
619        }
620
621        fn was_flr_initiated(&self) -> bool {
622            self.flr_initiated.load(Ordering::Acquire)
623        }
624
625        fn reset(&self) {
626            self.flr_initiated.store(false, Ordering::Release);
627        }
628    }
629
630    impl FlrHandler for TestFlrHandler {
631        fn initiate_flr(&self) {
632            self.flr_initiated.store(true, Ordering::Release);
633        }
634    }
635
636    impl Inspect for TestFlrHandler {
637        fn inspect(&self, req: inspect::Request<'_>) {
638            req.respond()
639                .field("flr_initiated", self.flr_initiated.load(Ordering::Acquire));
640        }
641    }
642
643    #[test]
644    fn test_pci_express_capability_read_u32_endpoint() {
645        let flr_handler = TestFlrHandler::new();
646        let cap = PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler));
647
648        // Test PCIe Capabilities Register (offset 0x00)
649        let caps_val = cap.read_u32(0x00);
650        assert_eq!(caps_val & 0xFF, 0x10); // Capability ID = 0x10
651        assert_eq!((caps_val >> 8) & 0xFF, 0x00); // Next Pointer = 0x00
652        assert_eq!((caps_val >> 16) & 0xFFFF, 0x0002); // PCIe Caps: Version 2, Device/Port Type 0
653
654        // Test Device Capabilities Register (offset 0x04)
655        let device_caps_val = cap.read_u32(0x04);
656        assert_eq!(
657            device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK,
658            PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK
659        ); // FLR bit should be set
660
661        // Test Device Control/Status Register (offset 0x08) - should be zero initially
662        let device_ctl_sts_val = cap.read_u32(0x08);
663        assert_eq!(device_ctl_sts_val, 0); // Both control and status should be 0
664
665        // Test Link Control/Status Register (offset 0x10) - should have link status initialized
666        let link_ctl_sts_val = cap.read_u32(0x10);
667        let expected_link_status = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
668            | ((LinkWidth::X16.into_bits() as u16) << 4); // current_link_speed + negotiated_link_width
669        assert_eq!(link_ctl_sts_val, (expected_link_status as u32) << 16); // Link status is in upper 16 bits
670    }
671
672    #[test]
673    fn test_pci_express_capability_read_u32_root_port() {
674        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
675
676        // Test PCIe Capabilities Register (offset 0x00)
677        let caps_val = cap.read_u32(0x00);
678        assert_eq!(caps_val & 0xFF, 0x10); // Capability ID = 0x10
679        assert_eq!((caps_val >> 8) & 0xFF, 0x00); // Next Pointer = 0x00
680        assert_eq!((caps_val >> 16) & 0xFFFF, 0x0042); // PCIe Caps: Version 2, Device/Port Type 4
681    }
682
683    #[test]
684    fn test_pci_express_capability_read_u32_no_flr() {
685        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
686
687        // Test Device Capabilities Register (offset 0x04) - FLR should not be set
688        let device_caps_val = cap.read_u32(0x04);
689        assert_eq!(device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK, 0);
690    }
691
692    #[test]
693    fn test_pci_express_capability_write_u32_readonly_registers() {
694        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
695
696        // Try to write to read-only PCIe Capabilities Register (offset 0x00)
697        let original_caps = cap.read_u32(0x00);
698        cap.write_u32(0x00, 0xFFFFFFFF);
699        assert_eq!(cap.read_u32(0x00), original_caps); // Should be unchanged
700
701        // Try to write to read-only Device Capabilities Register (offset 0x04)
702        let original_device_caps = cap.read_u32(0x04);
703        cap.write_u32(0x04, 0xFFFFFFFF);
704        assert_eq!(cap.read_u32(0x04), original_device_caps); // Should be unchanged
705    }
706
707    #[test]
708    fn test_pci_express_capability_write_u32_device_control() {
709        let flr_handler = TestFlrHandler::new();
710        let mut cap =
711            PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
712
713        // Initial state should have FLR bit clear
714        let initial_ctl_sts = cap.read_u32(0x08);
715        assert_eq!(initial_ctl_sts & 0xFFFF, 0); // Device Control should be 0
716
717        // Test writing to Device Control Register (lower 16 bits of offset 0x08)
718        // Set some control bits but not FLR initially
719        cap.write_u32(0x08, 0x0001); // Enable correctable error reporting (bit 0)
720        let device_ctl_sts = cap.read_u32(0x08);
721        assert_eq!(device_ctl_sts & 0xFFFF, 0x0001); // Device Control should be set
722        assert!(!flr_handler.was_flr_initiated()); // FLR should not be triggered
723
724        // Test FLR initiation (bit 15 of Device Control)
725        flr_handler.reset();
726        cap.write_u32(0x08, 0x8001); // Set FLR bit (bit 15) and other control bits
727        let device_ctl_sts_after_flr = cap.read_u32(0x08);
728        assert_eq!(device_ctl_sts_after_flr & 0xFFFF, 0x0001); // FLR bit should be cleared, others remain
729        assert!(flr_handler.was_flr_initiated()); // FLR should be triggered
730
731        // Test that writing FLR bit when it's already been triggered behaves correctly
732        flr_handler.reset();
733        // After the previous FLR, device_control should have bit 0 set but FLR clear
734        // So writing 0x8000 (only FLR bit) should trigger FLR again
735        cap.write_u32(0x08, 0x8000); // Set FLR bit only
736        let device_ctl_sts_final = cap.read_u32(0x08);
737        assert_eq!(device_ctl_sts_final & 0xFFFF, 0x0000); // All bits should be cleared (FLR self-clears, bit 0 was overwritten)
738        assert!(flr_handler.was_flr_initiated()); // Should trigger because FLR transitioned from 0 to 1
739    }
740
741    #[test]
742    fn test_pci_express_capability_write_u32_device_status() {
743        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
744
745        // Manually set some status bits to test write-1-to-clear behavior
746        {
747            let mut state = cap.state.lock();
748            state.device_status.set_correctable_error_detected(true);
749            state.device_status.set_non_fatal_error_detected(true);
750            state.device_status.set_fatal_error_detected(true);
751            state.device_status.set_unsupported_request_detected(true);
752        }
753
754        // Check that status bits are set
755        let device_ctl_sts = cap.read_u32(0x08);
756        let status_bits = (device_ctl_sts >> 16) & 0xFFFF;
757        assert_ne!(status_bits & 0x0F, 0); // Some status bits should be set
758
759        // Write 1 to clear correctable error bit (bit 0 of status)
760        cap.write_u32(0x08, 0x00010000); // Write 1 to bit 16 (correctable error in upper 16 bits)
761        let device_ctl_sts_after = cap.read_u32(0x08);
762        let status_bits_after = (device_ctl_sts_after >> 16) & 0xFFFF;
763        assert_eq!(status_bits_after & 0x01, 0); // Correctable error bit should be cleared
764        assert_ne!(status_bits_after & 0x0E, 0); // Other error bits should still be set
765
766        // Clear all remaining error bits
767        cap.write_u32(0x08, 0x000E0000); // Write 1 to bits 17-19 (other error bits)
768        let final_status = (cap.read_u32(0x08) >> 16) & 0xFFFF;
769        assert_eq!(final_status & 0x0F, 0); // All error bits should be cleared
770    }
771
772    #[test]
773    fn test_pci_express_capability_write_u32_unhandled_offset() {
774        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
775
776        // Writing to unhandled offset should not panic
777        cap.write_u32(0x10, 0xFFFFFFFF);
778        // Should not crash and should not affect other registers
779        assert_eq!(cap.read_u32(0x08), 0); // Device Control/Status should still be 0
780    }
781
782    #[test]
783    fn test_pci_express_capability_reset() {
784        let flr_handler = TestFlrHandler::new();
785        let mut cap =
786            PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
787
788        // Set some state
789        cap.write_u32(0x08, 0x0001); // Set some device control bits
790
791        // Manually set some status bits
792        {
793            let mut state = cap.state.lock();
794            state.device_status.set_correctable_error_detected(true);
795        }
796
797        // Verify state is set
798        let device_ctl_sts = cap.read_u32(0x08);
799        assert_ne!(device_ctl_sts, 0);
800
801        // Reset the capability
802        cap.reset();
803
804        // Verify state is cleared
805        let device_ctl_sts_after_reset = cap.read_u32(0x08);
806        assert_eq!(device_ctl_sts_after_reset, 0);
807    }
808
809    #[test]
810    fn test_pci_express_capability_extended_registers() {
811        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
812
813        // Test that extended registers return proper default values and don't crash
814        // Link Capabilities should have default speed (Speed32_0GtS) and width (X16)
815        let expected_link_caps =
816            LinkSpeed::Speed32_0GtS.into_bits() | (LinkWidth::X16.into_bits() << 4); // speed + (width << 4) = 5 + (16 << 4) = 5 + 256 = 261
817        assert_eq!(cap.read_u32(0x0C), expected_link_caps); // Link Capabilities
818        // Link Control/Status should have Link Status with current_link_speed=5 and negotiated_link_width=16
819        let expected_link_ctl_sts = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
820            | ((LinkWidth::X16.into_bits() as u16) << 4); // current_link_speed (bits 0-3) + negotiated_link_width (bits 4-9) = 5 + (16 << 4) = 5 + 256 = 261
821        assert_eq!(cap.read_u32(0x10), (expected_link_ctl_sts as u32) << 16); // Link Control/Status (status in upper 16 bits)
822        assert_eq!(cap.read_u32(0x14), 0); // Slot Capabilities
823        assert_eq!(cap.read_u32(0x18), 0); // Slot Control/Status
824        assert_eq!(cap.read_u32(0x1C), 0); // Root Control/Capabilities
825        assert_eq!(cap.read_u32(0x20), 0); // Root Status
826        assert_eq!(cap.read_u32(0x24), 0); // Device Capabilities 2
827        assert_eq!(cap.read_u32(0x28), 0); // Device Control/Status 2
828        // Link Capabilities 2 has supported_link_speeds_vector set to UpToGen5
829        let expected_link_caps_2 = SupportedLinkSpeedsVector::UpToGen5.into_bits() << 1; // supported_link_speeds_vector at bits 1-7 = 31 << 1 = 62
830        assert_eq!(cap.read_u32(0x2C), expected_link_caps_2); // Link Capabilities 2
831        // Link Control/Status 2 - Link Control 2 should have target_link_speed set to Speed32_0GtS (5)
832        let expected_link_ctl_sts_2 = LinkSpeed::Speed32_0GtS.into_bits() as u16; // target_link_speed in lower 4 bits = 5
833        assert_eq!(cap.read_u32(0x30), expected_link_ctl_sts_2 as u32); // Link Control/Status 2
834        assert_eq!(cap.read_u32(0x34), 0); // Slot Capabilities 2
835        assert_eq!(cap.read_u32(0x38), 0); // Slot Control/Status 2
836    }
837
838    #[test]
839    fn test_pci_express_capability_length() {
840        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
841        assert_eq!(cap.len(), 0x3C); // Should be 60 bytes (0x3C)
842    }
843
844    #[test]
845    fn test_pci_express_capability_label() {
846        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
847        assert_eq!(cap.label(), "pci-express");
848    }
849
850    #[test]
851    fn test_pci_express_capability_with_hotplug_support() {
852        // Test with RootPort (should work)
853        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
854        let cap_with_hotplug = cap.with_hotplug_support(1);
855
856        // Verify that the method doesn't crash and returns the capability
857        assert_eq!(cap_with_hotplug.label(), "pci-express");
858        assert_eq!(cap_with_hotplug.len(), 0x3C);
859
860        // Verify hotplug capabilities are set
861        assert!(cap_with_hotplug.slot_capabilities.hot_plug_surprise());
862        assert!(cap_with_hotplug.slot_capabilities.hot_plug_capable());
863        assert_eq!(cap_with_hotplug.slot_capabilities.physical_slot_number(), 1);
864
865        // Verify that slot_implemented is set in PCIe capabilities
866        assert!(
867            cap_with_hotplug.pcie_capabilities.slot_implemented(),
868            "slot_implemented should be true when hotplug is enabled"
869        );
870
871        // Test with DownstreamSwitchPort (should work)
872        let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
873        let cap2_with_hotplug = cap2.with_hotplug_support(2);
874
875        assert!(cap2_with_hotplug.slot_capabilities.hot_plug_surprise());
876        assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
877        assert_eq!(
878            cap2_with_hotplug.slot_capabilities.physical_slot_number(),
879            2
880        );
881
882        // Verify that slot_implemented is set for downstream switch port too
883        assert!(
884            cap2_with_hotplug.pcie_capabilities.slot_implemented(),
885            "slot_implemented should be true when hotplug is enabled"
886        );
887
888        // Test that non-hotplug capability doesn't have slot_implemented set
889        let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
890        assert!(
891            !cap_no_hotplug.pcie_capabilities.slot_implemented(),
892            "slot_implemented should be false when hotplug is not enabled"
893        );
894    }
895
896    #[test]
897    #[should_panic(expected = "Hotplug support is not valid for device port type Endpoint")]
898    fn test_pci_express_capability_with_hotplug_support_endpoint_panics() {
899        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
900        cap.with_hotplug_support(1);
901    }
902
903    #[test]
904    #[should_panic(
905        expected = "Hotplug support is not valid for device port type UpstreamSwitchPort"
906    )]
907    fn test_pci_express_capability_with_hotplug_support_upstream_panics() {
908        let cap = PciExpressCapability::new(DevicePortType::UpstreamSwitchPort, None);
909        cap.with_hotplug_support(1);
910    }
911
912    #[test]
913    fn test_slot_control_write_protection() {
914        // Create a root port capability with hotplug support but limited slot capabilities
915        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
916        cap = cap.with_hotplug_support(1);
917
918        // Modify slot capabilities to disable some features for testing
919        cap.slot_capabilities.set_attention_button_present(false);
920        cap.slot_capabilities.set_power_controller_present(false);
921        cap.slot_capabilities.set_mrl_sensor_present(false);
922        cap.slot_capabilities.set_attention_indicator_present(false);
923        cap.slot_capabilities.set_power_indicator_present(false);
924        cap.slot_capabilities
925            .set_electromechanical_interlock_present(false);
926        cap.slot_capabilities.set_no_command_completed_support(true);
927
928        // Try to write to slot control register with all bits set
929        let slot_ctl_sts_offset = 0x18; // SLOT_CTL_STS offset
930        let val_to_write = 0xFFFFFFFF; // All bits set in both control and status
931
932        cap.write_u32(slot_ctl_sts_offset, val_to_write);
933
934        // Read back the slot control register (lower 16 bits)
935        let read_back = cap.read_u32(slot_ctl_sts_offset);
936        let slot_control_value = read_back as u16;
937        let slot_control = pci_express::SlotControl::from_bits(slot_control_value);
938
939        // Verify that features not present in capabilities were not set in control register
940        assert!(
941            !slot_control.attention_button_pressed_enable(),
942            "Attention button enable should be 0 when capability not present"
943        );
944        assert!(
945            !slot_control.power_controller_control(),
946            "Power controller control should be 0 when capability not present"
947        );
948        assert!(
949            !slot_control.mrl_sensor_changed_enable(),
950            "MRL sensor changed enable should be 0 when capability not present"
951        );
952        assert_eq!(
953            slot_control.attention_indicator_control(),
954            0,
955            "Attention indicator control should be 0 when capability not present"
956        );
957        assert_eq!(
958            slot_control.power_indicator_control(),
959            0,
960            "Power indicator control should be 0 when capability not present"
961        );
962        assert!(
963            !slot_control.electromechanical_interlock_control(),
964            "Electromechanical interlock control should be 0 when capability not present"
965        );
966        assert!(
967            !slot_control.command_completed_interrupt_enable(),
968            "Command completed interrupt enable should be 0 when no command completed support"
969        );
970
971        // However, hotplug interrupt enable should be settable since hotplug is capable
972        assert!(
973            slot_control.hot_plug_interrupt_enable(),
974            "Hotplug interrupt enable should be settable when hotplug capable"
975        );
976    }
977
978    #[test]
979    fn test_link_control_retrain_link_behavior() {
980        // Test that retrain_link always reads as 0 regardless of what is written
981        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
982
983        let link_ctl_sts_offset = 0x10; // LINK_CTL_STS offset
984
985        // Write a value with retrain_link bit set (bit 5)
986        let write_val = 0x0020; // retrain_link bit (bit 5) = 1
987        cap.write_u32(link_ctl_sts_offset, write_val);
988
989        // Read back and verify retrain_link is always 0
990        let read_back = cap.read_u32(link_ctl_sts_offset);
991        let link_control = pci_express::LinkControl::from_bits(read_back as u16);
992
993        assert!(
994            !link_control.retrain_link(),
995            "retrain_link should always read as 0"
996        );
997
998        // Verify other bits can still be set (except retrain_link)
999        let write_val_2 = 0x0001; // aspm_control bit 0 = 1
1000        cap.write_u32(link_ctl_sts_offset, write_val_2);
1001
1002        let read_back_2 = cap.read_u32(link_ctl_sts_offset);
1003        let link_control_2 = pci_express::LinkControl::from_bits(read_back_2 as u16);
1004
1005        assert_eq!(
1006            link_control_2.aspm_control(),
1007            1,
1008            "Other control bits should be settable"
1009        );
1010        assert!(
1011            !link_control_2.retrain_link(),
1012            "retrain_link should still read as 0"
1013        );
1014    }
1015
1016    #[test]
1017    fn test_hotplug_link_capabilities() {
1018        // Test that Data Link Layer Link Active Reporting is enabled with hotplug
1019        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1020        let cap_with_hotplug = cap.with_hotplug_support(1);
1021
1022        let link_caps_offset = 0x0C; // LINK_CAPS offset
1023        let link_caps = cap_with_hotplug.read_u32(link_caps_offset);
1024        let link_capabilities = pci_express::LinkCapabilities::from_bits(link_caps);
1025
1026        // Verify that Data Link Layer Link Active Reporting is enabled
1027        assert!(
1028            link_capabilities.data_link_layer_link_active_reporting(),
1029            "Data Link Layer Link Active Reporting should be enabled for hotplug"
1030        );
1031
1032        // Verify default speed and width are still correct
1033        assert_eq!(
1034            link_capabilities.max_link_speed(),
1035            LinkSpeed::Speed32_0GtS.into_bits(),
1036            "Max link speed should be Speed32_0GtS (PCIe 32.0 GT/s)"
1037        );
1038        assert_eq!(
1039            link_capabilities.max_link_width(),
1040            LinkWidth::X16.into_bits(),
1041            "Max link width should be X16 (x16)"
1042        );
1043
1044        // Test that non-hotplug capability doesn't have Data Link Layer Link Active Reporting
1045        let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1046        let link_caps_no_hotplug = cap_no_hotplug.read_u32(link_caps_offset);
1047        let link_capabilities_no_hotplug =
1048            pci_express::LinkCapabilities::from_bits(link_caps_no_hotplug);
1049
1050        assert!(
1051            !link_capabilities_no_hotplug.data_link_layer_link_active_reporting(),
1052            "Data Link Layer Link Active Reporting should be disabled without hotplug"
1053        );
1054    }
1055
1056    #[test]
1057    fn test_link_status_read_only() {
1058        // Test that Link Status register is read-only and cannot be modified by writes
1059        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1060
1061        let link_ctl_sts_offset = 0x10; // LINK_CTL_STS offset
1062
1063        // Set some initial link status values (this would normally be done by hardware)
1064        {
1065            let mut state = cap.state.lock();
1066            state.link_status.set_current_link_speed(0b0001); // Set initial speed
1067            state.link_status.set_negotiated_link_width(0b000001); // Set initial width
1068            state.link_status.set_link_training(true); // Set link training active
1069            state.link_status.set_data_link_layer_link_active(true); // Set DLL active
1070        }
1071
1072        // Read initial values
1073        let initial_read = cap.read_u32(link_ctl_sts_offset);
1074        let initial_link_status = pci_express::LinkStatus::from_bits((initial_read >> 16) as u16);
1075
1076        // Verify initial values are set
1077        assert_eq!(
1078            initial_link_status.current_link_speed(),
1079            0b0001,
1080            "Initial link speed should be set"
1081        );
1082        assert_eq!(
1083            initial_link_status.negotiated_link_width(),
1084            0b000001,
1085            "Initial link width should be set"
1086        );
1087        assert!(
1088            initial_link_status.link_training(),
1089            "Initial link training should be active"
1090        );
1091        assert!(
1092            initial_link_status.data_link_layer_link_active(),
1093            "Initial DLL should be active"
1094        );
1095
1096        // Try to write different values to Link Status (upper 16 bits) while also writing to Link Control
1097        let write_val = 0xFFFF0001; // Upper 16 bits all 1s (Link Status), lower 16 bits = 1 (Link Control)
1098        cap.write_u32(link_ctl_sts_offset, write_val);
1099
1100        // Read back and verify Link Status hasn't changed
1101        let after_write = cap.read_u32(link_ctl_sts_offset);
1102        let final_link_status = pci_express::LinkStatus::from_bits((after_write >> 16) as u16);
1103        let final_link_control = pci_express::LinkControl::from_bits(after_write as u16);
1104
1105        // Link Status should remain unchanged (read-only)
1106        assert_eq!(
1107            final_link_status.current_link_speed(),
1108            initial_link_status.current_link_speed(),
1109            "Link Status current_link_speed should be read-only"
1110        );
1111        assert_eq!(
1112            final_link_status.negotiated_link_width(),
1113            initial_link_status.negotiated_link_width(),
1114            "Link Status negotiated_link_width should be read-only"
1115        );
1116        assert_eq!(
1117            final_link_status.link_training(),
1118            initial_link_status.link_training(),
1119            "Link Status link_training should be read-only"
1120        );
1121        assert_eq!(
1122            final_link_status.data_link_layer_link_active(),
1123            initial_link_status.data_link_layer_link_active(),
1124            "Link Status data_link_layer_link_active should be read-only"
1125        );
1126
1127        // But Link Control should be modifiable
1128        assert_eq!(
1129            final_link_control.aspm_control(),
1130            1,
1131            "Link Control should be writable"
1132        );
1133    }
1134
1135    #[test]
1136    fn test_slot_status_rw1c_behavior() {
1137        // Create a root port capability with hotplug support
1138        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1139        cap = cap.with_hotplug_support(1);
1140
1141        let slot_ctl_sts_offset = 0x18; // SLOT_CTL_STS offset
1142
1143        // First, simulate setting some status bits (this would normally be done by hardware)
1144        {
1145            let mut state = cap.state.lock();
1146            state.slot_status.set_attention_button_pressed(true);
1147            state.slot_status.set_power_fault_detected(true);
1148            state.slot_status.set_mrl_sensor_changed(true);
1149            state.slot_status.set_presence_detect_changed(true);
1150            state.slot_status.set_command_completed(true);
1151            state.slot_status.set_data_link_layer_state_changed(true);
1152            // Set some RO bits too
1153            state.slot_status.set_mrl_sensor_state(1);
1154            state.slot_status.set_presence_detect_state(1);
1155            state.slot_status.set_electromechanical_interlock_status(1);
1156        }
1157
1158        // Read the initial status to verify all bits are set
1159        let initial_read = cap.read_u32(slot_ctl_sts_offset);
1160        let initial_status = pci_express::SlotStatus::from_bits((initial_read >> 16) as u16);
1161        assert!(
1162            initial_status.attention_button_pressed(),
1163            "Initial attention button pressed should be set"
1164        );
1165        assert!(
1166            initial_status.power_fault_detected(),
1167            "Initial power fault detected should be set"
1168        );
1169        assert!(
1170            initial_status.mrl_sensor_changed(),
1171            "Initial MRL sensor changed should be set"
1172        );
1173        assert!(
1174            initial_status.presence_detect_changed(),
1175            "Initial presence detect changed should be set"
1176        );
1177        assert!(
1178            initial_status.command_completed(),
1179            "Initial command completed should be set"
1180        );
1181        assert!(
1182            initial_status.data_link_layer_state_changed(),
1183            "Initial data link layer state changed should be set"
1184        );
1185        assert_eq!(
1186            initial_status.mrl_sensor_state(),
1187            1,
1188            "Initial MRL sensor state should be set"
1189        );
1190        assert_eq!(
1191            initial_status.presence_detect_state(),
1192            1,
1193            "Initial presence detect state should be set"
1194        );
1195        assert_eq!(
1196            initial_status.electromechanical_interlock_status(),
1197            1,
1198            "Initial electromechanical interlock status should be set"
1199        );
1200
1201        // Write 1 to clear specific RW1C bits (upper 16 bits contain status)
1202        // Write 1s only to some RW1C bits to test selective clearing
1203        // Bit positions: attention_button_pressed(0), command_completed(4), data_link_layer_state_changed(8)
1204        let write_val = (0b0000_0001_0001_0001_u16 as u32) << 16; // Clear bits 0, 4, and 8
1205        cap.write_u32(slot_ctl_sts_offset, write_val);
1206
1207        // Read back and verify RW1C behavior
1208        let after_write = cap.read_u32(slot_ctl_sts_offset);
1209        let final_status = pci_express::SlotStatus::from_bits((after_write >> 16) as u16);
1210
1211        // RW1C bits that were written with 1 should be cleared
1212        assert!(
1213            !final_status.attention_button_pressed(),
1214            "Attention button pressed should be cleared after write-1"
1215        );
1216        assert!(
1217            !final_status.command_completed(),
1218            "Command completed should be cleared after write-1"
1219        );
1220        assert!(
1221            !final_status.data_link_layer_state_changed(),
1222            "Data link layer state changed should be cleared after write-1"
1223        );
1224
1225        // RW1C bits that were written with 0 should remain unchanged
1226        assert!(
1227            final_status.power_fault_detected(),
1228            "Power fault detected should remain set (write-0)"
1229        );
1230        assert!(
1231            final_status.mrl_sensor_changed(),
1232            "MRL sensor changed should remain set (write-0)"
1233        );
1234        assert!(
1235            final_status.presence_detect_changed(),
1236            "Presence detect changed should remain set (write-0)"
1237        );
1238
1239        // RO bits should remain unchanged regardless of what was written
1240        assert_eq!(
1241            final_status.mrl_sensor_state(),
1242            1,
1243            "MRL sensor state should remain unchanged (RO)"
1244        );
1245        assert_eq!(
1246            final_status.presence_detect_state(),
1247            1,
1248            "Presence detect state should remain unchanged (RO)"
1249        );
1250        assert_eq!(
1251            final_status.electromechanical_interlock_status(),
1252            1,
1253            "Electromechanical interlock status should remain unchanged (RO)"
1254        );
1255    }
1256
1257    #[test]
1258    fn test_link_control_2_target_speed_validation() {
1259        // Test that target link speed is validated against max link speed and reflected in link status
1260        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1261
1262        let link_ctl_sts_2_offset = 0x30; // LINK_CTL_STS_2 offset
1263
1264        // Initially, target link speed should be Speed32_0GtS (5) and current link speed should match
1265        let initial_read = cap.read_u32(link_ctl_sts_2_offset);
1266        let initial_link_control_2 = pci_express::LinkControl2::from_bits(initial_read as u16);
1267        assert_eq!(
1268            initial_link_control_2.target_link_speed(),
1269            LinkSpeed::Speed32_0GtS.into_bits() as u16,
1270            "Initial target link speed should be Speed32_0GtS"
1271        );
1272
1273        // Check that link status reflects this speed
1274        let link_ctl_sts_offset = 0x10; // LINK_CTL_STS offset
1275        let link_ctl_sts = cap.read_u32(link_ctl_sts_offset);
1276        let link_status = pci_express::LinkStatus::from_bits((link_ctl_sts >> 16) as u16);
1277        assert_eq!(
1278            link_status.current_link_speed(),
1279            LinkSpeed::Speed32_0GtS.into_bits() as u16,
1280            "Initial current link speed should match target speed"
1281        );
1282        assert_eq!(
1283            link_status.negotiated_link_width(),
1284            LinkWidth::X16.into_bits() as u16,
1285            "Initial negotiated link width should be X16"
1286        );
1287
1288        // Test writing a valid speed (Speed16_0GtS = 4) that's less than max speed (Speed32_0GtS = 5)
1289        let valid_speed = LinkSpeed::Speed16_0GtS.into_bits() as u16; // 4
1290        cap.write_u32(link_ctl_sts_2_offset, valid_speed as u32);
1291
1292        // Verify target link speed was set correctly
1293        let after_valid_write = cap.read_u32(link_ctl_sts_2_offset);
1294        let link_control_2_after_valid =
1295            pci_express::LinkControl2::from_bits(after_valid_write as u16);
1296        assert_eq!(
1297            link_control_2_after_valid.target_link_speed(),
1298            valid_speed,
1299            "Target link speed should be set to requested valid speed"
1300        );
1301
1302        // Verify current link speed was updated in link status
1303        let link_ctl_sts_after_valid = cap.read_u32(link_ctl_sts_offset);
1304        let link_status_after_valid =
1305            pci_express::LinkStatus::from_bits((link_ctl_sts_after_valid >> 16) as u16);
1306        assert_eq!(
1307            link_status_after_valid.current_link_speed(),
1308            valid_speed,
1309            "Current link speed should be updated to match target speed"
1310        );
1311
1312        // Test writing an invalid speed (Speed64_0GtS = 6) that exceeds max speed (Speed32_0GtS = 5)
1313        let invalid_speed = LinkSpeed::Speed64_0GtS.into_bits() as u16; // 6
1314        cap.write_u32(link_ctl_sts_2_offset, invalid_speed as u32);
1315
1316        // Verify target link speed was clamped to max speed
1317        let after_invalid_write = cap.read_u32(link_ctl_sts_2_offset);
1318        let link_control_2_after_invalid =
1319            pci_express::LinkControl2::from_bits(after_invalid_write as u16);
1320        let max_speed = LinkSpeed::Speed32_0GtS.into_bits() as u16; // 5
1321        assert_eq!(
1322            link_control_2_after_invalid.target_link_speed(),
1323            max_speed,
1324            "Target link speed should be clamped to max supported speed"
1325        );
1326
1327        // Verify current link speed was updated to the clamped value
1328        let link_ctl_sts_after_invalid = cap.read_u32(link_ctl_sts_offset);
1329        let link_status_after_invalid =
1330            pci_express::LinkStatus::from_bits((link_ctl_sts_after_invalid >> 16) as u16);
1331        assert_eq!(
1332            link_status_after_invalid.current_link_speed(),
1333            max_speed,
1334            "Current link speed should be updated to clamped max speed"
1335        );
1336
1337        // Verify that link width remains unchanged throughout
1338        assert_eq!(
1339            link_status_after_valid.negotiated_link_width(),
1340            LinkWidth::X16.into_bits() as u16,
1341            "Negotiated link width should remain unchanged"
1342        );
1343        assert_eq!(
1344            link_status_after_invalid.negotiated_link_width(),
1345            LinkWidth::X16.into_bits() as u16,
1346            "Negotiated link width should remain unchanged"
1347        );
1348    }
1349
1350    #[test]
1351    fn test_with_hotplug_support_slot_number() {
1352        // Test that slot numbers are properly set when enabling hotplug support
1353
1354        // Test with slot number 5
1355        let cap1 = PciExpressCapability::new(DevicePortType::RootPort, None);
1356        let cap1_with_hotplug = cap1.with_hotplug_support(5);
1357
1358        assert!(cap1_with_hotplug.slot_capabilities.hot_plug_capable());
1359        assert_eq!(
1360            cap1_with_hotplug.slot_capabilities.physical_slot_number(),
1361            5
1362        );
1363
1364        // Test with slot number 0
1365        let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
1366        let cap2_with_hotplug = cap2.with_hotplug_support(0);
1367
1368        assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
1369        assert_eq!(
1370            cap2_with_hotplug.slot_capabilities.physical_slot_number(),
1371            0
1372        );
1373
1374        // Test with a larger slot number
1375        let cap3 = PciExpressCapability::new(DevicePortType::RootPort, None);
1376        let cap3_with_hotplug = cap3.with_hotplug_support(255);
1377
1378        assert!(cap3_with_hotplug.slot_capabilities.hot_plug_capable());
1379        assert_eq!(
1380            cap3_with_hotplug.slot_capabilities.physical_slot_number(),
1381            255
1382        );
1383    }
1384
1385    #[test]
1386    fn test_slot_implemented_flag_in_pcie_capabilities_register() {
1387        // Test that slot_implemented bit is correctly set in the PCIe Capabilities register
1388        // when hotplug support is enabled
1389
1390        // Test without hotplug - slot_implemented should be false
1391        let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1392        let caps_val_no_hotplug = cap_no_hotplug.read_u32(0x00);
1393        let pcie_caps_no_hotplug = (caps_val_no_hotplug >> 16) as u16;
1394        let slot_implemented_bit = (pcie_caps_no_hotplug >> 8) & 0x1; // slot_implemented is bit 8 of PCIe capabilities
1395        assert_eq!(
1396            slot_implemented_bit, 0,
1397            "slot_implemented should be 0 when hotplug is not enabled"
1398        );
1399
1400        // Test with hotplug - slot_implemented should be true
1401        let cap_with_hotplug = cap_no_hotplug.with_hotplug_support(1);
1402        let caps_val_with_hotplug = cap_with_hotplug.read_u32(0x00);
1403        let pcie_caps_with_hotplug = (caps_val_with_hotplug >> 16) as u16;
1404        let slot_implemented_bit_hotplug = (pcie_caps_with_hotplug >> 8) & 0x1; // slot_implemented is bit 8 of PCIe capabilities
1405        assert_eq!(
1406            slot_implemented_bit_hotplug, 1,
1407            "slot_implemented should be 1 when hotplug is enabled"
1408        );
1409    }
1410
1411    #[test]
1412    fn test_set_presence_detect_state() {
1413        // Test setting presence detect state on a hotplug-capable port
1414        let cap = PciExpressCapability::new(DevicePortType::RootPort, None).with_hotplug_support(1);
1415
1416        // Initially, presence detect state should be 0 (no device present)
1417        let initial_slot_status = cap.read_u32(0x18); // Slot Control + Slot Status
1418        let initial_presence_detect = (initial_slot_status >> 22) & 0x1; // presence_detect_state is bit 6 of slot status (upper 16 bits)
1419        assert_eq!(
1420            initial_presence_detect, 0,
1421            "Initial presence detect state should be 0"
1422        );
1423
1424        // Set device as present
1425        cap.set_presence_detect_state(true);
1426        let present_slot_status = cap.read_u32(0x18);
1427        let present_presence_detect = (present_slot_status >> 22) & 0x1;
1428        assert_eq!(
1429            present_presence_detect, 1,
1430            "Presence detect state should be 1 when device is present"
1431        );
1432
1433        // Set device as not present
1434        cap.set_presence_detect_state(false);
1435        let absent_slot_status = cap.read_u32(0x18);
1436        let absent_presence_detect = (absent_slot_status >> 22) & 0x1;
1437        assert_eq!(
1438            absent_presence_detect, 0,
1439            "Presence detect state should be 0 when device is not present"
1440        );
1441    }
1442
1443    #[test]
1444    fn test_set_presence_detect_state_without_slot_implemented() {
1445        // Test that setting presence detect state is silently ignored when slot is not implemented
1446        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1447
1448        // Should not panic and should be silently ignored
1449        cap.set_presence_detect_state(true);
1450        cap.set_presence_detect_state(false);
1451    }
1452}