pci_core/
spec.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Types and constants specified by the PCI spec.
5//!
6//! This module MUST NOT contain any vendor-specific constants!
7
8pub mod hwid {
9    //! Hardware ID types and constants
10
11    #![expect(missing_docs)] // constants/fields are self-explanatory
12
13    use core::fmt;
14    use inspect::Inspect;
15
16    /// A collection of hard-coded hardware IDs specific to a particular PCI
17    /// device, as reflected in their corresponding PCI configuration space
18    /// registers.
19    ///
20    /// See PCI 2.3 Spec - 6.2.1 for details on each of these fields.
21    #[derive(Debug, Copy, Clone, Inspect)]
22    pub struct HardwareIds {
23        #[inspect(hex)]
24        pub vendor_id: u16,
25        #[inspect(hex)]
26        pub device_id: u16,
27        #[inspect(hex)]
28        pub revision_id: u8,
29        pub prog_if: ProgrammingInterface,
30        pub sub_class: Subclass,
31        pub base_class: ClassCode,
32        // TODO: this struct should be re-jigged when adding support for other
33        // header types (e.g: type 1)
34        #[inspect(hex)]
35        pub type0_sub_vendor_id: u16,
36        #[inspect(hex)]
37        pub type0_sub_system_id: u16,
38    }
39
40    open_enum::open_enum! {
41        /// ClassCode identifies the PCI device's type.
42        ///
43        /// Values pulled from <https://wiki.osdev.org/PCI#Class_Codes>.
44        #[derive(Inspect)]
45        #[inspect(display)]
46        pub enum ClassCode: u8 {
47            UNCLASSIFIED = 0x00,
48            MASS_STORAGE_CONTROLLER = 0x01,
49            NETWORK_CONTROLLER = 0x02,
50            DISPLAY_CONTROLLER = 0x03,
51            MULTIMEDIA_CONTROLLER = 0x04,
52            MEMORY_CONTROLLER = 0x05,
53            BRIDGE = 0x06,
54            SIMPLE_COMMUNICATION_CONTROLLER = 0x07,
55            BASE_SYSTEM_PERIPHERAL = 0x08,
56            INPUT_DEVICE_CONTROLLER = 0x09,
57            DOCKING_STATION = 0x0A,
58            PROCESSOR = 0x0B,
59            SERIAL_BUS_CONTROLLER = 0x0C,
60            WIRELESS_CONTROLLER = 0x0D,
61            INTELLIGENT_CONTROLLER = 0x0E,
62            SATELLITE_COMMUNICATION_CONTROLLER = 0x0F,
63            ENCRYPTION_CONTROLLER = 0x10,
64            SIGNAL_PROCESSING_CONTROLLER = 0x11,
65            PROCESSING_ACCELERATOR = 0x12,
66            NONESSENTIAL_INSTRUMENTATION = 0x13,
67            // 0x14 - 0x3F: Reserved
68            CO_PROCESSOR = 0x40,
69            // 0x41 - 0xFE: Reserved
70            /// Vendor specific
71            UNASSIGNED = 0xFF,
72        }
73    }
74
75    impl ClassCode {
76        pub fn is_reserved(&self) -> bool {
77            let c = &self.0;
78            (0x14..=0x3f).contains(c) || (0x41..=0xfe).contains(c)
79        }
80    }
81
82    impl fmt::Display for ClassCode {
83        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84            if self.is_reserved() {
85                return write!(f, "RESERVED({:#04x})", self.0);
86            }
87            fmt::Debug::fmt(self, f)
88        }
89    }
90
91    impl From<u8> for ClassCode {
92        fn from(c: u8) -> Self {
93            Self(c)
94        }
95    }
96
97    impl From<ClassCode> for u8 {
98        fn from(c: ClassCode) -> Self {
99            c.0
100        }
101    }
102
103    // Most subclass/programming interface values aren't used, and don't have names that can easily be made into variable
104    // identifiers (eg, "ISA Compatibility mode controller, supports both channels switched to PCI native mode, supports bus mastering").
105    //
106    // Therefore, only add values as needed.
107
108    open_enum::open_enum! {
109        /// SubclassCode identifies the PCI device's function.
110        ///
111        /// Values pulled from <https://wiki.osdev.org/PCI#Class_Codes>.
112        #[derive(Inspect)]
113        #[inspect(transparent(hex))]
114        pub enum Subclass: u8 {
115            // TODO: As more values are used, add them here.
116
117            NONE = 0x00,
118
119            // Mass Storage Controller (Class code: 0x01)
120            MASS_STORAGE_CONTROLLER_NON_VOLATILE_MEMORY = 0x08,
121
122            // Network Controller (Class code: 0x02)
123            // Other values: 0x01 - 0x08, 0x80
124            NETWORK_CONTROLLER_ETHERNET = 0x00,
125
126            // Bridge (Class code: 0x06)
127            // Other values: 0x02 - 0x0A
128            BRIDGE_HOST = 0x00,
129            BRIDGE_ISA = 0x01,
130            BRIDGE_PCI_TO_PCI = 0x04,
131            BRIDGE_OTHER = 0x80,
132
133            // Base System Peripheral (Class code: 0x08)
134            // Other values: 0x00 - 0x06
135            BASE_SYSTEM_PERIPHERAL_OTHER = 0x80,
136        }
137    }
138
139    impl From<u8> for Subclass {
140        fn from(c: u8) -> Self {
141            Self(c)
142        }
143    }
144
145    impl From<Subclass> for u8 {
146        fn from(c: Subclass) -> Self {
147            c.0
148        }
149    }
150
151    open_enum::open_enum! {
152        /// ProgrammingInterface (aka, program interface byte) identifies the PCI device's
153        /// register-level programming interface.
154        ///
155        /// Values pulled from <https://wiki.osdev.org/PCI#Class_Codes>.
156        #[derive(Inspect)]
157        #[inspect(transparent(hex))]
158        pub enum ProgrammingInterface: u8{
159            // TODO: As more values are used, add them here.
160
161            NONE = 0x00,
162
163            // Non-Volatile Memory Controller (Class code:0x01, Subclass: 0x08)
164            // Other values: 0x01
165            MASS_STORAGE_CONTROLLER_NON_VOLATILE_MEMORY_NVME = 0x02,
166
167            // Ethernet Controller (Class code: 0x02, Subclass: 0x00)
168            NETWORK_CONTROLLER_ETHERNET_GDMA = 0x01,
169        }
170    }
171
172    impl From<u8> for ProgrammingInterface {
173        fn from(c: u8) -> Self {
174            Self(c)
175        }
176    }
177
178    impl From<ProgrammingInterface> for u8 {
179        fn from(c: ProgrammingInterface) -> Self {
180            c.0
181        }
182    }
183}
184
185/// Configuration Space
186///
187/// Sources: PCI 2.3 Spec - Chapter 6
188#[expect(missing_docs)] // primarily enums/structs with self-explanatory variants
189pub mod cfg_space {
190    use bitfield_struct::bitfield;
191    use inspect::Inspect;
192    use zerocopy::FromBytes;
193    use zerocopy::Immutable;
194    use zerocopy::IntoBytes;
195    use zerocopy::KnownLayout;
196
197    open_enum::open_enum! {
198        /// Offsets into the type 00h configuration space header.
199        ///
200        /// Table pulled from <https://wiki.osdev.org/PCI>
201        ///
202        /// | Offset | Bits 31-24                 | Bits 23-16  | Bits 15-8           | Bits 7-0             |
203        /// |--------|----------------------------|-------------|---------------------|--------------------- |
204        /// | 0x0    | Device ID                  |             | Vendor ID           |                      |
205        /// | 0x4    | Status                     |             | Command             |                      |
206        /// | 0x8    | Class code                 |             |                     | Revision ID          |
207        /// | 0xC    | BIST                       | Header type | Latency Timer       | Cache Line Size      |
208        /// | 0x10   | Base address #0 (BAR0)     |             |                     |                      |
209        /// | 0x14   | Base address #1 (BAR1)     |             |                     |                      |
210        /// | 0x18   | Base address #2 (BAR2)     |             |                     |                      |
211        /// | 0x1C   | Base address #3 (BAR3)     |             |                     |                      |
212        /// | 0x20   | Base address #4 (BAR4)     |             |                     |                      |
213        /// | 0x24   | Base address #5 (BAR5)     |             |                     |                      |
214        /// | 0x28   | Cardbus CIS Pointer        |             |                     |                      |
215        /// | 0x2C   | Subsystem ID               |             | Subsystem Vendor ID |                      |
216        /// | 0x30   | Expansion ROM base address |             |                     |                      |
217        /// | 0x34   | Reserved                   |             |                     | Capabilities Pointer |
218        /// | 0x38   | Reserved                   |             |                     |                      |
219        /// | 0x3C   | Max latency                | Min Grant   | Interrupt PIN       | Interrupt Line       |
220        pub enum HeaderType00: u16 {
221            DEVICE_VENDOR      = 0x00,
222            STATUS_COMMAND     = 0x04,
223            CLASS_REVISION     = 0x08,
224            BIST_HEADER        = 0x0C,
225            BAR0               = 0x10,
226            BAR1               = 0x14,
227            BAR2               = 0x18,
228            BAR3               = 0x1C,
229            BAR4               = 0x20,
230            BAR5               = 0x24,
231            CARDBUS_CIS_PTR    = 0x28,
232            SUBSYSTEM_ID       = 0x2C,
233            EXPANSION_ROM_BASE = 0x30,
234            RESERVED_CAP_PTR   = 0x34,
235            RESERVED           = 0x38,
236            LATENCY_INTERRUPT  = 0x3C,
237        }
238    }
239
240    pub const HEADER_TYPE_00_SIZE: u16 = 0x40;
241
242    open_enum::open_enum! {
243        /// Offsets into the type 01h configuration space header.
244        ///
245        /// Table pulled from <https://wiki.osdev.org/PCI>
246        ///
247        /// | Offset | Bits 31-24                       | Bits 23-16             | Bits 15-8                | Bits 7-0             |
248        /// |--------|----------------------------------|------------------------|--------------------------|--------------------- |
249        /// | 0x0    | Device ID                        |                        | Vendor ID                |                      |
250        /// | 0x4    | Status                           |                        | Command                  |                      |
251        /// | 0x8    | Class code                       |                        |                          | Revision ID          |
252        /// | 0xC    | BIST                             | Header Type            | Latency Timer            | Cache Line Size      |
253        /// | 0x10   | Base address #0 (BAR0)           |                        |                          |                      |
254        /// | 0x14   | Base address #1 (BAR1)           |                        |                          |                      |
255        /// | 0x18   | Secondary Latency Timer          | Subordinate Bus Number | Secondary Bus Number     | Primary Bus Number   |
256        /// | 0x1C   | Secondary Status                 |                        | I/O Limit                | I/O Base             |
257        /// | 0x20   | Memory Limit                     |                        | Memory Base              |                      |
258        /// | 0x24   | Prefetchable Memory Limit        |                        | Prefetchable Memory Base |                      |
259        /// | 0x28   | Prefetchable Base Upper 32 Bits  |                        |                          |                      |
260        /// | 0x2C   | Prefetchable Limit Upper 32 Bits |                        |                          |                      |
261        /// | 0x30   | I/O Limit Upper 16 Bits          |                        | I/O Base Upper 16 Bits   |                      |
262        /// | 0x34   | Reserved                         |                        |                          | Capabilities Pointer |
263        /// | 0x38   | Expansion ROM Base Address       |                        |                          |                      |
264        /// | 0x3C   | Bridge Control                   |                        | Interrupt PIN            | Interrupt Line       |
265        pub enum HeaderType01: u16 {
266            DEVICE_VENDOR         = 0x00,
267            STATUS_COMMAND        = 0x04,
268            CLASS_REVISION        = 0x08,
269            BIST_HEADER           = 0x0C,
270            BAR0                  = 0x10,
271            BAR1                  = 0x14,
272            LATENCY_BUS_NUMBERS   = 0x18,
273            SEC_STATUS_IO_RANGE   = 0x1C,
274            MEMORY_RANGE          = 0x20,
275            PREFETCH_RANGE        = 0x24,
276            PREFETCH_BASE_UPPER   = 0x28,
277            PREFETCH_LIMIT_UPPER  = 0x2C,
278            IO_RANGE_UPPER        = 0x30,
279            RESERVED_CAP_PTR      = 0x34,
280            EXPANSION_ROM_BASE    = 0x38,
281            BRDIGE_CTRL_INTERRUPT = 0x3C,
282        }
283    }
284
285    pub const HEADER_TYPE_01_SIZE: u16 = 0x40;
286
287    /// BAR in-band encoding bits.
288    ///
289    /// The low bits of the BAR are not actually part of the address.
290    /// Instead, they are used to in-band encode various bits of
291    /// metadata about the BAR, and are masked off when determining the
292    /// actual address.
293    #[bitfield(u32)]
294    pub struct BarEncodingBits {
295        pub use_pio: bool,
296
297        _reserved: bool,
298
299        /// False indicates 32 bit.
300        /// Only used in MMIO
301        pub type_64_bit: bool,
302        pub prefetchable: bool,
303
304        #[bits(28)]
305        _reserved2: u32,
306    }
307
308    /// Command Register
309    #[derive(Inspect)]
310    #[bitfield(u16)]
311    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
312    pub struct Command {
313        pub pio_enabled: bool,
314        pub mmio_enabled: bool,
315        pub bus_master: bool,
316        pub special_cycles: bool,
317        pub enable_memory_write_invalidate: bool,
318        pub vga_palette_snoop: bool,
319        pub parity_error_response: bool,
320        /// must be 0
321        #[bits(1)]
322        _reserved: u16,
323        pub enable_serr: bool,
324        pub enable_fast_b2b: bool,
325        pub intx_disable: bool,
326        #[bits(5)]
327        _reserved2: u16,
328    }
329
330    /// Status Register
331    #[bitfield(u16)]
332    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
333    pub struct Status {
334        #[bits(3)]
335        _reserved: u16,
336        pub interrupt_status: bool,
337        pub capabilities_list: bool,
338        pub capable_mhz_66: bool,
339        _reserved2: bool,
340        pub capable_fast_b2b: bool,
341        pub err_master_parity: bool,
342
343        #[bits(2)]
344        pub devsel: DevSel,
345
346        pub abort_target_signaled: bool,
347        pub abort_target_received: bool,
348        pub abort_master_received: bool,
349        pub err_signaled: bool,
350        pub err_detected_parity: bool,
351    }
352
353    #[derive(Debug)]
354    #[repr(u16)]
355    pub enum DevSel {
356        Fast = 0b00,
357        Medium = 0b01,
358        Slow = 0b10,
359    }
360
361    impl DevSel {
362        const fn from_bits(bits: u16) -> Self {
363            match bits {
364                0b00 => DevSel::Fast,
365                0b01 => DevSel::Medium,
366                0b10 => DevSel::Slow,
367                _ => unreachable!(),
368            }
369        }
370
371        const fn into_bits(self) -> u16 {
372            self as u16
373        }
374    }
375}
376
377/// Capabilities
378pub mod caps {
379    open_enum::open_enum! {
380        /// Capability IDs
381        ///
382        /// Sources: PCI 2.3 Spec - Appendix H
383        ///
384        /// NOTE: this is a non-exhaustive list, so don't be afraid to add new
385        /// variants on an as-needed basis!
386        pub enum CapabilityId: u8 {
387            #![expect(missing_docs)] // self explanatory variants
388            VENDOR_SPECIFIC = 0x09,
389            PCI_EXPRESS     = 0x10,
390            MSIX            = 0x11,
391        }
392    }
393
394    /// MSI-X
395    #[expect(missing_docs)] // primarily enums/structs with self-explanatory variants
396    pub mod msix {
397        open_enum::open_enum! {
398            /// Offsets into the MSI-X Capability Header
399            ///
400            /// Table pulled from <https://wiki.osdev.org/PCI>
401            ///
402            /// | Offset    | Bits 31-24         | Bits 23-16 | Bits 15-8    | Bits 7-3             | Bits 2-0 |
403            /// |-----------|--------------------|------------|--------------|----------------------|----------|
404            /// | Cap + 0x0 | Message Control    |            | Next Pointer | Capability ID (0x11) |          |
405            /// | Cap + 0x4 | Table Offset       |            |              |                      | BIR      |
406            /// | Cap + 0x8 | Pending Bit Offset |            |              |                      | BIR      |
407            pub enum MsixCapabilityHeader: u16 {
408                CONTROL_CAPS = 0x00,
409                OFFSET_TABLE = 0x04,
410                OFFSET_PBA   = 0x08,
411            }
412        }
413
414        open_enum::open_enum! {
415            /// Offsets into a single MSI-X Table Entry
416            pub enum MsixTableEntryIdx: u16 {
417                MSG_ADDR_LO = 0x00,
418                MSG_ADDR_HI = 0x04,
419                MSG_DATA    = 0x08,
420                VECTOR_CTL  = 0x0C,
421            }
422        }
423    }
424
425    /// PCI Express
426    #[expect(missing_docs)] // primarily enums/structs with self-explanatory variants
427    pub mod pci_express {
428        use bitfield_struct::bitfield;
429        use inspect::Inspect;
430        use zerocopy::FromBytes;
431        use zerocopy::Immutable;
432        use zerocopy::IntoBytes;
433        use zerocopy::KnownLayout;
434
435        open_enum::open_enum! {
436            /// Offsets into the PCI Express Capability Header
437            ///
438            /// Table pulled from PCI Express Base Specification Rev. 3.0
439            ///
440            /// | Offset    | Bits 31-24       | Bits 23-16       | Bits 15-8        | Bits 7-0             |
441            /// |-----------|------------------|----------------- |------------------|----------------------|
442            /// | Cap + 0x0 | PCI Express Capabilities Register   | Next Pointer     | Capability ID (0x10) |
443            /// | Cap + 0x4 | Device Capabilities Register                                                  |
444            /// | Cap + 0x8 | Device Status    | Device Control                                             |
445            /// | Cap + 0xC | Link Capabilities Register                                                    |
446            /// | Cap + 0x10| Link Status      | Link Control                                               |
447            /// | Cap + 0x14| Slot Capabilities Register                                                    |
448            /// | Cap + 0x18| Slot Status      | Slot Control                                               |
449            /// | Cap + 0x1C| Root Capabilities| Root Control                                               |
450            /// | Cap + 0x20| Root Status Register                                                          |
451            /// | Cap + 0x24| Device Capabilities 2 Register                                                |
452            /// | Cap + 0x28| Device Status 2  | Device Control 2                                           |
453            /// | Cap + 0x2C| Link Capabilities 2 Register                                                  |
454            /// | Cap + 0x30| Link Status 2    | Link Control 2                                             |
455            /// | Cap + 0x34| Slot Capabilities 2 Register                                                  |
456            /// | Cap + 0x38| Slot Status 2    | Slot Control 2                                             |
457            pub enum PciExpressCapabilityHeader: u16 {
458                PCIE_CAPS           = 0x00,
459                DEVICE_CAPS         = 0x04,
460                DEVICE_CTL_STS      = 0x08,
461                LINK_CAPS           = 0x0C,
462                LINK_CTL_STS        = 0x10,
463                SLOT_CAPS           = 0x14,
464                SLOT_CTL_STS        = 0x18,
465                ROOT_CTL_CAPS       = 0x1C,
466                ROOT_STS            = 0x20,
467                DEVICE_CAPS_2       = 0x24,
468                DEVICE_CTL_STS_2    = 0x28,
469                LINK_CAPS_2         = 0x2C,
470                LINK_CTL_STS_2      = 0x30,
471                SLOT_CAPS_2         = 0x34,
472                SLOT_CTL_STS_2      = 0x38,
473            }
474        }
475
476        /// PCI Express Capabilities Register
477        #[bitfield(u16)]
478        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
479        pub struct PciExpressCapabilities {
480            #[bits(4)]
481            pub capability_version: u16,
482            #[bits(4)]
483            pub device_port_type: DevicePortType,
484            pub slot_implemented: bool,
485            #[bits(5)]
486            pub interrupt_message_number: u16,
487            pub _undefined: bool,
488            pub flit_mode_supported: bool,
489        }
490
491        #[derive(Debug)]
492        #[repr(u16)]
493        pub enum DevicePortType {
494            Endpoint = 0b0000,
495            RootPort = 0b0100,
496            UpstreamSwitchPort = 0b0101,
497            DownstreamSwitchPort = 0b0110,
498        }
499
500        impl DevicePortType {
501            const fn from_bits(bits: u16) -> Self {
502                match bits {
503                    0b0000 => DevicePortType::Endpoint,
504                    0b0100 => DevicePortType::RootPort,
505                    0b0101 => DevicePortType::UpstreamSwitchPort,
506                    0b0110 => DevicePortType::DownstreamSwitchPort,
507                    _ => unreachable!(),
508                }
509            }
510
511            const fn into_bits(self) -> u16 {
512                self as u16
513            }
514        }
515
516        /// Device Capabilities Register (From the 6.4 spec)
517        #[bitfield(u32)]
518        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
519        pub struct DeviceCapabilities {
520            #[bits(3)]
521            pub max_payload_size: u32,
522            #[bits(2)]
523            pub phantom_functions: u32,
524            pub ext_tag_field: bool,
525            #[bits(3)]
526            pub endpoint_l0s_latency: u32,
527            #[bits(3)]
528            pub endpoint_l1_latency: u32,
529            #[bits(3)]
530            _reserved1: u32,
531            pub role_based_error: bool,
532            pub err_cor_subclass_capable: bool,
533            pub rx_mps_fixed: bool,
534            #[bits(8)]
535            pub captured_slot_power_limit: u32,
536            #[bits(2)]
537            pub captured_slot_power_scale: u32,
538            pub function_level_reset: bool,
539            pub mixed_mps_supported: bool,
540            pub tee_io_supported: bool,
541            _reserved3: bool,
542        }
543
544        /// Device Control Register
545        #[bitfield(u16)]
546        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
547        pub struct DeviceControl {
548            pub correctable_error_reporting_enable: bool,
549            pub non_fatal_error_reporting_enable: bool,
550            pub fatal_error_reporting_enable: bool,
551            pub unsupported_request_reporting_enable: bool,
552            pub enable_relaxed_ordering: bool,
553            #[bits(3)]
554            pub max_payload_size: u16,
555            pub extended_tag_enable: bool,
556            pub phantom_functions_enable: bool,
557            pub aux_power_pm_enable: bool,
558            pub enable_no_snoop: bool,
559            #[bits(3)]
560            pub max_read_request_size: u16,
561            pub initiate_function_level_reset: bool,
562        }
563
564        /// Device Status Register
565        #[bitfield(u16)]
566        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
567        pub struct DeviceStatus {
568            pub correctable_error_detected: bool,
569            pub non_fatal_error_detected: bool,
570            pub fatal_error_detected: bool,
571            pub unsupported_request_detected: bool,
572            pub aux_power_detected: bool,
573            pub transactions_pending: bool,
574            #[bits(10)]
575            _reserved: u16,
576        }
577
578        /// Link Capabilities Register
579        #[bitfield(u32)]
580        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
581        pub struct LinkCapabilities {
582            #[bits(4)]
583            pub max_link_speed: u32,
584            #[bits(6)]
585            pub max_link_width: u32,
586            #[bits(2)]
587            pub aspm_support: u32,
588            #[bits(3)]
589            pub l0s_exit_latency: u32,
590            #[bits(3)]
591            pub l1_exit_latency: u32,
592            pub clock_power_management: bool,
593            pub surprise_down_error_reporting: bool,
594            pub data_link_layer_link_active_reporting: bool,
595            pub link_bandwidth_notification_capability: bool,
596            pub aspm_optionality_compliance: bool,
597            #[bits(1)]
598            _reserved: u32,
599            #[bits(8)]
600            pub port_number: u32,
601        }
602
603        /// Link Control Register
604        #[bitfield(u16)]
605        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
606        pub struct LinkControl {
607            #[bits(2)]
608            pub aspm_control: u16,
609            pub ptm_propagation_delay_adaptation_interpretation_b: bool,
610            #[bits(1)]
611            pub read_completion_boundary: u16,
612            pub link_disable: bool,
613            pub retrain_link: bool,
614            pub common_clock_configuration: bool,
615            pub extended_synch: bool,
616            pub enable_clock_power_management: bool,
617            pub hardware_autonomous_width_disable: bool,
618            pub link_bandwidth_management_interrupt_enable: bool,
619            pub link_autonomous_bandwidth_interrupt_enable: bool,
620            #[bits(1)]
621            pub sris_clocking: u16,
622            pub flit_mode_disable: bool,
623            #[bits(2)]
624            pub drs_signaling_control: u16,
625        }
626
627        /// Link Status Register
628        #[bitfield(u16)]
629        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
630        pub struct LinkStatus {
631            #[bits(4)]
632            pub current_link_speed: u16,
633            #[bits(6)]
634            pub negotiated_link_width: u16,
635            #[bits(1)]
636            _reserved: u16,
637            pub link_training: bool,
638            pub slot_clock_configuration: bool,
639            pub data_link_layer_link_active: bool,
640            pub link_bandwidth_management_status: bool,
641            pub link_autonomous_bandwidth_status: bool,
642        }
643
644        /// Slot Capabilities Register
645        #[bitfield(u32)]
646        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
647        pub struct SlotCapabilities {
648            pub attention_button_present: bool,
649            pub power_controller_present: bool,
650            pub mrl_sensor_present: bool,
651            pub attention_indicator_present: bool,
652            pub power_indicator_present: bool,
653            pub hot_plug_surprise: bool,
654            pub hot_plug_capable: bool,
655            #[bits(8)]
656            pub slot_power_limit_value: u32,
657            #[bits(2)]
658            pub slot_power_limit_scale: u32,
659            pub electromechanical_interlock_present: bool,
660            pub no_command_completed_support: bool,
661            #[bits(13)]
662            pub physical_slot_number: u32,
663        }
664
665        /// Slot Control Register
666        #[bitfield(u16)]
667        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
668        pub struct SlotControl {
669            pub attention_button_pressed_enable: bool,
670            pub power_fault_detected_enable: bool,
671            pub mrl_sensor_changed_enable: bool,
672            pub presence_detect_changed_enable: bool,
673            pub command_completed_interrupt_enable: bool,
674            pub hot_plug_interrupt_enable: bool,
675            #[bits(2)]
676            pub attention_indicator_control: u16,
677            #[bits(2)]
678            pub power_indicator_control: u16,
679            pub power_controller_control: bool,
680            pub electromechanical_interlock_control: bool,
681            pub data_link_layer_state_changed_enable: bool,
682            pub auto_slot_power_limit_enable: bool,
683            pub in_band_pd_disable: bool,
684            #[bits(1)]
685            _reserved: u16,
686        }
687
688        /// Slot Status Register
689        #[bitfield(u16)]
690        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
691        pub struct SlotStatus {
692            pub attention_button_pressed: bool,
693            pub power_fault_detected: bool,
694            pub mrl_sensor_changed: bool,
695            pub presence_detect_changed: bool,
696            pub command_completed: bool,
697            #[bits(1)]
698            pub mrl_sensor_state: u16,
699            #[bits(1)]
700            pub presence_detect_state: u16,
701            #[bits(1)]
702            pub electromechanical_interlock_status: u16,
703            pub data_link_layer_state_changed: bool,
704            #[bits(7)]
705            _reserved: u16,
706        }
707
708        /// Root Control Register
709        #[bitfield(u16)]
710        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
711        pub struct RootControl {
712            pub system_error_on_correctable_error_enable: bool,
713            pub system_error_on_non_fatal_error_enable: bool,
714            pub system_error_on_fatal_error_enable: bool,
715            pub pme_interrupt_enable: bool,
716            pub crs_software_visibility_enable: bool,
717            pub no_nfm_subtree_below_this_root_port: bool,
718            #[bits(10)]
719            _reserved: u16,
720        }
721
722        /// Root Capabilities Register
723        #[bitfield(u16)]
724        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
725        pub struct RootCapabilities {
726            pub crs_software_visibility: bool,
727            #[bits(15)]
728            _reserved: u16,
729        }
730
731        /// Root Status Register
732        #[bitfield(u32)]
733        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
734        pub struct RootStatus {
735            #[bits(16)]
736            pub pme_requester_id: u32,
737            pub pme_status: bool,
738            pub pme_pending: bool,
739            #[bits(14)]
740            _reserved: u32,
741        }
742
743        /// Device Capabilities 2 Register
744        #[bitfield(u32)]
745        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
746        pub struct DeviceCapabilities2 {
747            #[bits(4)]
748            pub completion_timeout_ranges_supported: u32,
749            pub completion_timeout_disable_supported: bool,
750            pub ari_forwarding_supported: bool,
751            pub atomic_op_routing_supported: bool,
752            pub atomic_op_32_bit_completer_supported: bool,
753            pub atomic_op_64_bit_completer_supported: bool,
754            pub cas_128_bit_completer_supported: bool,
755            pub no_ro_enabled_pr_pr_passing: bool,
756            pub ltr_mechanism_supported: bool,
757            #[bits(2)]
758            pub tph_completer_supported: u32,
759            #[bits(2)]
760            _reserved: u32,
761            pub ten_bit_tag_completer_supported: bool,
762            pub ten_bit_tag_requester_supported: bool,
763            #[bits(2)]
764            pub obff_supported: u32,
765            pub extended_fmt_field_supported: bool,
766            pub end_end_tlp_prefix_supported: bool,
767            #[bits(2)]
768            pub max_end_end_tlp_prefixes: u32,
769            #[bits(2)]
770            pub emergency_power_reduction_supported: u32,
771            pub emergency_power_reduction_init_required: bool,
772            #[bits(1)]
773            _reserved: u32,
774            pub dmwr_completer_supported: bool,
775            #[bits(2)]
776            pub dmwr_lengths_supported: u32,
777            pub frs_supported: bool,
778        }
779
780        /// Device Control 2 Register
781        #[bitfield(u16)]
782        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
783        pub struct DeviceControl2 {
784            #[bits(4)]
785            pub completion_timeout_value: u16,
786            pub completion_timeout_disable: bool,
787            pub ari_forwarding_enable: bool,
788            pub atomic_op_requester_enable: bool,
789            pub atomic_op_egress_blocking: bool,
790            pub ido_request_enable: bool,
791            pub ido_completion_enable: bool,
792            pub ltr_mechanism_enable: bool,
793            pub emergency_power_reduction_request: bool,
794            pub ten_bit_tag_requester_enable: bool,
795            #[bits(2)]
796            pub obff_enable: u16,
797            pub end_end_tlp_prefix_blocking: bool,
798        }
799
800        /// Device Status 2 Register
801        #[bitfield(u16)]
802        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
803        pub struct DeviceStatus2 {
804            #[bits(16)]
805            _reserved: u16,
806        }
807
808        /// Link Capabilities 2 Register
809        #[bitfield(u32)]
810        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
811        pub struct LinkCapabilities2 {
812            #[bits(1)]
813            _reserved: u32,
814            #[bits(7)]
815            pub supported_link_speeds_vector: u32,
816            pub crosslink_supported: bool,
817            #[bits(7)]
818            pub lower_skp_os_generation_supported_speeds_vector: u32,
819            #[bits(7)]
820            pub lower_skp_os_reception_supported_speeds_vector: u32,
821            pub retimer_presence_detect_supported: bool,
822            pub two_retimers_presence_detect_supported: bool,
823            #[bits(6)]
824            _reserved: u32,
825            pub drs_supported: bool,
826        }
827
828        /// Link Control 2 Register
829        #[bitfield(u16)]
830        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
831        pub struct LinkControl2 {
832            #[bits(4)]
833            pub target_link_speed: u16,
834            pub enter_compliance: bool,
835            pub hardware_autonomous_speed_disable: bool,
836            #[bits(1)]
837            pub selectable_de_emphasis: u16,
838            #[bits(3)]
839            pub transmit_margin: u16,
840            pub enter_modified_compliance: bool,
841            pub compliance_sos: bool,
842            #[bits(4)]
843            pub compliance_preset_de_emphasis: u16,
844        }
845
846        /// Link Status 2 Register
847        #[bitfield(u16)]
848        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
849        pub struct LinkStatus2 {
850            #[bits(1)]
851            pub current_de_emphasis_level: u16,
852            pub equalization_8gts_complete: bool,
853            pub equalization_8gts_phase_1_successful: bool,
854            pub equalization_8gts_phase_2_successful: bool,
855            pub equalization_8gts_phase_3_successful: bool,
856            pub link_equalization_request_8gts: bool,
857            pub retimer_presence_detected: bool,
858            pub two_retimers_presence_detected: bool,
859            #[bits(2)]
860            pub crosslink_resolution: u16,
861            pub flit_mode_status: bool,
862            #[bits(1)]
863            _reserved: u16,
864            #[bits(3)]
865            pub downstream_component_presence: u16,
866            pub drs_message_received: bool,
867        }
868
869        /// Slot Capabilities 2 Register
870        #[bitfield(u32)]
871        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
872        pub struct SlotCapabilities2 {
873            pub in_band_pd_disable_supported: bool,
874            #[bits(31)]
875            _reserved: u32,
876        }
877
878        /// Slot Control 2 Register
879        #[bitfield(u16)]
880        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
881        pub struct SlotControl2 {
882            #[bits(16)]
883            _reserved: u16,
884        }
885
886        /// Slot Status 2 Register
887        #[bitfield(u16)]
888        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
889        pub struct SlotStatus2 {
890            #[bits(16)]
891            _reserved: u16,
892        }
893    }
894}