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