pci_types/
register.rs

1use bit_field::BitField;
2use core::{
3    convert::TryFrom,
4    fmt::{self, Debug, Formatter},
5};
6
7/// Slowest time that a device will assert DEVSEL# for any bus command except Configuration Space
8/// read and writes
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum DevselTiming {
11    Fast = 0x0,
12    Medium = 0x1,
13    Slow = 0x2,
14}
15
16#[derive(Debug)]
17pub struct TryFromDevselTimingError {
18    number: u8,
19}
20
21impl fmt::Display for TryFromDevselTimingError {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        write!(f, "No discriminant in `DevselTiming` matches the value `{}`", self.number)
24    }
25}
26
27impl TryFrom<u8> for DevselTiming {
28    type Error = TryFromDevselTimingError;
29
30    fn try_from(value: u8) -> Result<Self, Self::Error> {
31        match value {
32            0x0 => Ok(DevselTiming::Fast),
33            0x1 => Ok(DevselTiming::Medium),
34            0x2 => Ok(DevselTiming::Slow),
35            number => Err(TryFromDevselTimingError { number }),
36        }
37    }
38}
39
40#[derive(Clone, Copy, Eq, PartialEq)]
41pub struct StatusRegister(u16);
42
43impl StatusRegister {
44    pub fn new(value: u16) -> Self {
45        StatusRegister(value)
46    }
47
48    /// Will be `true` whenever the device detects a parity error, even if parity error handling is disabled.
49    pub fn parity_error_detected(&self) -> bool {
50        self.0.get_bit(15)
51    }
52
53    /// Will be `true` whenever the device asserts SERR#.
54    pub fn signalled_system_error(&self) -> bool {
55        self.0.get_bit(14)
56    }
57
58    /// Will return `true`, by a master device, whenever its transaction
59    /// (except for Special Cycle transactions) is terminated with Master-Abort.
60    pub fn received_master_abort(&self) -> bool {
61        self.0.get_bit(13)
62    }
63
64    /// Will return `true`, by a master device, whenever its transaction is terminated with Target-Abort.
65    pub fn received_target_abort(&self) -> bool {
66        self.0.get_bit(12)
67    }
68
69    /// Will return `true` whenever a target device terminates a transaction with Target-Abort.
70    pub fn signalled_target_abort(&self) -> bool {
71        self.0.get_bit(11)
72    }
73
74    /// The slowest time that a device will assert DEVSEL# for any bus command except
75    /// Configuration Space read and writes.
76    ///
77    /// For PCIe always set to `Fast`
78    pub fn devsel_timing(&self) -> Result<DevselTiming, TryFromDevselTimingError> {
79        let bits = self.0.get_bits(9..11);
80        DevselTiming::try_from(bits as u8)
81    }
82
83    /// This returns `true` only when the following conditions are met:
84    /// - The bus agent asserted PERR# on a read or observed an assertion of PERR# on a write
85    /// - the agent setting the bit acted as the bus master for the operation in which the error occurred
86    /// - bit 6 of the Command register (Parity Error Response bit) is set to 1.
87    pub fn master_data_parity_error(&self) -> bool {
88        self.0.get_bit(8)
89    }
90
91    /// If returns `true` the device can accept fast back-to-back transactions that are not from
92    /// the same agent; otherwise, transactions can only be accepted from the same agent.
93    ///
94    /// For PCIe always set to `false`
95    pub fn fast_back_to_back_capable(&self) -> bool {
96        self.0.get_bit(7)
97    }
98
99    /// If returns `true` the device is capable of running at 66 MHz; otherwise, the device runs at 33 MHz.
100    ///
101    /// For PCIe always set to `false`
102    pub fn capable_66mhz(&self) -> bool {
103        self.0.get_bit(5)
104    }
105
106    /// If returns `true` the device implements the pointer for a New Capabilities Linked list;
107    /// otherwise, the linked list is not available.
108    ///
109    /// For PCIe always set to `true`
110    pub fn has_capability_list(&self) -> bool {
111        self.0.get_bit(4)
112    }
113
114    /// Represents the state of the device's INTx# signal. If returns `true` and bit 10 of the
115    /// Command register (Interrupt Disable bit) is set to 0 the signal will be asserted;
116    /// otherwise, the signal will be ignored.
117    pub fn interrupt_status(&self) -> bool {
118        self.0.get_bit(3)
119    }
120}
121
122impl Debug for StatusRegister {
123    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
124        f.debug_struct("StatusRegister")
125            .field("parity_error_detected", &self.parity_error_detected())
126            .field("signalled_system_error", &self.signalled_system_error())
127            .field("received_master_abort", &self.received_master_abort())
128            .field("received_target_abort", &self.received_target_abort())
129            .field("signalled_target_abort", &self.signalled_target_abort())
130            .field("devsel_timing", &self.devsel_timing())
131            .field("master_data_parity_error", &self.master_data_parity_error())
132            .field("fast_back_to_back_capable", &self.fast_back_to_back_capable())
133            .field("capable_66mhz", &self.capable_66mhz())
134            .field("has_capability_list", &self.has_capability_list())
135            .field("interrupt_status", &self.interrupt_status())
136            .finish()
137    }
138}
139
140bitflags::bitflags! {
141    #[repr(transparent)]
142    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
143    pub struct CommandRegister: u16 {
144        const IO_ENABLE = 1 << 0;
145        const MEMORY_ENABLE = 1 << 1;
146        const BUS_MASTER_ENABLE = 1 << 2;
147        const SPECIAL_CYCLE_ENABLE = 1 << 3;
148        const MEMORY_WRITE_AND_INVALIDATE = 1 << 4;
149        const VGA_PALETTE_SNOOP = 1 << 5;
150        const PARITY_ERROR_RESPONSE = 1 << 6;
151        const IDSEL_STEP_WAIT_CYCLE_CONTROL = 1 << 7;
152        const SERR_ENABLE = 1 << 8;
153        const FAST_BACK_TO_BACK_ENABLE = 1 << 9;
154        const INTERRUPT_DISABLE = 1 << 10;
155        const _ = !0;
156    }
157}