pci: Split the configuration space offset into device-specific
This commit is contained in:
parent
3dd881dec5
commit
7634a27ba6
|
|
@ -9,10 +9,8 @@ use alloc::vec::Vec;
|
|||
use align_ext::AlignExt;
|
||||
|
||||
use self::{msix::CapabilityMsixData, vendor::CapabilityVndrData};
|
||||
use super::{
|
||||
cfg_space::{PciDeviceCommonCfgOffset, Status},
|
||||
common_device::PciCommonDevice,
|
||||
};
|
||||
use super::{cfg_space::Status, common_device::PciCommonDevice};
|
||||
use crate::cfg_space::PciGeneralDeviceCfgOffset;
|
||||
|
||||
pub mod msix;
|
||||
pub mod vendor;
|
||||
|
|
@ -91,18 +89,21 @@ impl Capability {
|
|||
if !dev.status().contains(Status::CAPABILITIES_LIST) {
|
||||
return Vec::new();
|
||||
}
|
||||
let mut capabilities = Vec::new();
|
||||
|
||||
// The offset of the first capability pointer is the same for PCI general devices and PCI bridge devices.
|
||||
const CAP_OFFSET: u16 = PciGeneralDeviceCfgOffset::CapabilitiesPointer as u16;
|
||||
let mut cap_ptr =
|
||||
(dev.location()
|
||||
.read8(PciDeviceCommonCfgOffset::CapabilitiesPointer as u16) as u16)
|
||||
.align_down(align_of::<u32>() as _);
|
||||
(dev.location().read8(CAP_OFFSET) as u16).align_down(align_of::<u32>() as _);
|
||||
let mut cap_ptr_vec = Vec::new();
|
||||
let mut capabilities = Vec::new();
|
||||
|
||||
// read all cap_ptr so that it is easy for us to get the length.
|
||||
while cap_ptr > 0 {
|
||||
cap_ptr_vec.push(cap_ptr);
|
||||
cap_ptr = (dev.location().read8(cap_ptr + 1) as u16).align_down(align_of::<u32>() as _);
|
||||
}
|
||||
cap_ptr_vec.sort();
|
||||
|
||||
// Push here so that we can calculate the length of the last capability.
|
||||
cap_ptr_vec.push(Self::CAPABILITY_TOP);
|
||||
let length = cap_ptr_vec.len();
|
||||
|
|
@ -143,6 +144,7 @@ impl Capability {
|
|||
cap_data: data,
|
||||
});
|
||||
}
|
||||
|
||||
capabilities
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ use spin::Once;
|
|||
|
||||
use super::PciDeviceLocation;
|
||||
|
||||
/// Offset in PCI device's common configuration space(Not the PCI bridge).
|
||||
/// Offset in PCI device's common configuration space.
|
||||
#[repr(u16)]
|
||||
pub enum PciDeviceCommonCfgOffset {
|
||||
pub enum PciCommonCfgOffset {
|
||||
/// Vendor ID
|
||||
VendorId = 0x00,
|
||||
/// Device ID
|
||||
|
|
@ -30,8 +30,12 @@ pub enum PciDeviceCommonCfgOffset {
|
|||
Status = 0x06,
|
||||
/// Revision ID
|
||||
RevisionId = 0x08,
|
||||
/// Class code
|
||||
ClassCode = 0x09,
|
||||
/// Programming Interface
|
||||
ProgIf = 0x09,
|
||||
/// Subclass code
|
||||
SubclassCode = 0x0A,
|
||||
/// Base class code
|
||||
BaseClassCode = 0x0B,
|
||||
/// Cache Line Size
|
||||
CacheLineSize = 0x0C,
|
||||
/// Latency Timer
|
||||
|
|
@ -40,6 +44,15 @@ pub enum PciDeviceCommonCfgOffset {
|
|||
HeaderType = 0x0E,
|
||||
/// BIST: Represents the status and allows control of a devices BIST(built-in self test).
|
||||
Bist = 0x0F,
|
||||
/// Interrupt Line
|
||||
InterruptLine = 0x3C,
|
||||
/// Interrupt Pin
|
||||
InterruptPin = 0x3D,
|
||||
}
|
||||
|
||||
/// Offset in PCI general device's configuration space (Not the PCI bridge or Cardbus bridge).
|
||||
#[repr(u16)]
|
||||
pub enum PciGeneralDeviceCfgOffset {
|
||||
/// Base Address Register #0
|
||||
Bar0 = 0x10,
|
||||
/// Base Address Register #1
|
||||
|
|
@ -62,16 +75,92 @@ pub enum PciDeviceCommonCfgOffset {
|
|||
XromBar = 0x30,
|
||||
/// Capabilities pointer
|
||||
CapabilitiesPointer = 0x34,
|
||||
/// Interrupt Line
|
||||
InterruptLine = 0x3C,
|
||||
/// INterrupt PIN
|
||||
InterruptPin = 0x3D,
|
||||
/// Min Grant
|
||||
MinGrant = 0x3E,
|
||||
/// Max latency
|
||||
MaxLatency = 0x3F,
|
||||
}
|
||||
|
||||
/// Offset in PCI-to-PCI bridge's configuration space.
|
||||
#[repr(u16)]
|
||||
pub enum PciBridgeCfgOffset {
|
||||
/// Base Address Register #0
|
||||
Bar0 = 0x10,
|
||||
/// Base Address Register #1
|
||||
Bar1 = 0x14,
|
||||
/// Primary bus number
|
||||
PrimaryBusNumber = 0x18,
|
||||
/// Secondary bus number
|
||||
SecondaryBusNumber = 0x19,
|
||||
/// Subordinate bus number
|
||||
SubordinateBusNumber = 0x1A,
|
||||
/// Secondary latency timer
|
||||
SecondaryLatencyTimer = 0x1B,
|
||||
/// I/O base
|
||||
IoBase = 0x1C,
|
||||
/// I/O limit
|
||||
IoLimit = 0x1D,
|
||||
/// Secondary status
|
||||
SecondaryStatus = 0x1E,
|
||||
/// Memory base
|
||||
MemoryBase = 0x20,
|
||||
/// Memory limit
|
||||
MemoryLimit = 0x22,
|
||||
/// Prefetchable memory base
|
||||
PrefetchableMemoryBase = 0x24,
|
||||
/// Prefetchable memory limit
|
||||
PrefetchableMemoryLimit = 0x26,
|
||||
/// Prefetchable memory base upper 32 bits
|
||||
PrefetchableMemoryBaseUpper32 = 0x28,
|
||||
/// Prefetchable memory limit upper 32 bits
|
||||
PrefetchableMemoryLimitUpper32 = 0x2C,
|
||||
/// I/O base upper 16 bits
|
||||
IoBaseUpper16 = 0x30,
|
||||
/// I/O limit upper 16 bits
|
||||
IoLimitUpper16 = 0x32,
|
||||
/// Capabilities pointer
|
||||
CapabilitiesPointer = 0x34,
|
||||
/// Bridge control
|
||||
BridgeControl = 0x3E,
|
||||
}
|
||||
|
||||
/// Offset in PCI-to-Cardbus bridge's configuration space.
|
||||
#[repr(u16)]
|
||||
pub enum PciCardbusBridgeCfgOffset {
|
||||
/// Cardbus socket/ExCA base address
|
||||
CardbusSocketExcaBaseAddress = 0x10,
|
||||
/// Capabilities pointer
|
||||
CapabilitiesPointer = 0x14,
|
||||
/// Secondary status
|
||||
SecondaryStatus = 0x16,
|
||||
/// Cardbus latency timer
|
||||
CardbusLatencyTimer = 0x17,
|
||||
/// Memory base 0
|
||||
MemoryBase0 = 0x18,
|
||||
/// Memory limit 0
|
||||
MemoryLimit0 = 0x1C,
|
||||
/// Memory base 1
|
||||
MemoryBase1 = 0x20,
|
||||
/// Memory limit 1
|
||||
MemoryLimit1 = 0x24,
|
||||
/// I/O base 0
|
||||
IoBase0 = 0x28,
|
||||
/// I/O limit 0
|
||||
IoLimit0 = 0x2C,
|
||||
/// I/O base 1
|
||||
IoBase1 = 0x30,
|
||||
/// I/O limit 1
|
||||
IoLimit1 = 0x34,
|
||||
/// Bridge control
|
||||
BridgeControl = 0x3E,
|
||||
/// Subsystem device ID
|
||||
SubsystemDeviceId = 0x40,
|
||||
/// Subsystem Vendor ID
|
||||
SubsystemVendorId = 0x42,
|
||||
/// Legacy mode base address
|
||||
LegacyModeBaseAddress = 0x44,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// PCI device common config space command register.
|
||||
pub struct Command: u16 {
|
||||
|
|
@ -163,7 +252,7 @@ impl Bar {
|
|||
return Err(Error::InvalidArgs);
|
||||
}
|
||||
|
||||
let offset = index as u16 * 4 + PciDeviceCommonCfgOffset::Bar0 as u16;
|
||||
let offset = index as u16 * 4 + PciGeneralDeviceCfgOffset::Bar0 as u16;
|
||||
let raw = location.read32(offset);
|
||||
|
||||
// Check the "Space Indicator" bit.
|
||||
|
|
@ -254,7 +343,7 @@ impl MemoryBar {
|
|||
_ => return Err(Error::InvalidArgs),
|
||||
};
|
||||
|
||||
let offset = index as u16 * 4 + PciDeviceCommonCfgOffset::Bar0 as u16;
|
||||
let offset = index as u16 * 4 + PciGeneralDeviceCfgOffset::Bar0 as u16;
|
||||
|
||||
// "Software saves the original value of the Base Address register, writes a value of all
|
||||
// 1's to the register, then reads it back."
|
||||
|
|
@ -396,7 +485,7 @@ impl IoBar {
|
|||
fn new(location: &PciDeviceLocation, index: u8, raw: u32) -> Result<Self> {
|
||||
debug_assert_eq!(raw & 1, 1);
|
||||
|
||||
let offset = index as u16 * 4 + PciDeviceCommonCfgOffset::Bar0 as u16;
|
||||
let offset = index as u16 * 4 + PciGeneralDeviceCfgOffset::Bar0 as u16;
|
||||
|
||||
// "Software saves the original value of the Base Address register, writes a value of all
|
||||
// 1's to the register, then reads it back."
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use alloc::vec::Vec;
|
|||
|
||||
use super::{
|
||||
capability::Capability,
|
||||
cfg_space::{AddrLen, Bar, Command, PciDeviceCommonCfgOffset, Status},
|
||||
cfg_space::{AddrLen, Bar, Command, PciCommonCfgOffset, Status},
|
||||
device_info::PciDeviceId,
|
||||
};
|
||||
use crate::device_info::PciDeviceLocation;
|
||||
|
|
@ -45,24 +45,18 @@ impl PciCommonDevice {
|
|||
|
||||
/// Gets the PCI Command
|
||||
pub fn command(&self) -> Command {
|
||||
Command::from_bits_truncate(
|
||||
self.location
|
||||
.read16(PciDeviceCommonCfgOffset::Command as u16),
|
||||
)
|
||||
Command::from_bits_truncate(self.location.read16(PciCommonCfgOffset::Command as u16))
|
||||
}
|
||||
|
||||
/// Sets the PCI Command
|
||||
pub fn set_command(&self, command: Command) {
|
||||
self.location
|
||||
.write16(PciDeviceCommonCfgOffset::Command as u16, command.bits())
|
||||
.write16(PciCommonCfgOffset::Command as u16, command.bits())
|
||||
}
|
||||
|
||||
/// Gets the PCI status
|
||||
pub fn status(&self) -> Status {
|
||||
Status::from_bits_truncate(
|
||||
self.location
|
||||
.read16(PciDeviceCommonCfgOffset::Status as u16),
|
||||
)
|
||||
Status::from_bits_truncate(self.location.read16(PciCommonCfgOffset::Status as u16))
|
||||
}
|
||||
|
||||
pub(super) fn new(location: PciDeviceLocation) -> Option<Self> {
|
||||
|
|
@ -114,7 +108,7 @@ impl BarManager {
|
|||
|
||||
/// Parse the BAR space by PCI device location.
|
||||
fn new(location: PciDeviceLocation) -> Self {
|
||||
let header_type = location.read8(PciDeviceCommonCfgOffset::HeaderType as u16) & !(1 << 7);
|
||||
let header_type = location.read8(PciCommonCfgOffset::HeaderType as u16) & !(1 << 7);
|
||||
// Get the max bar amount, header type=0 => end device; header type=1 => PCI bridge.
|
||||
let max = match header_type {
|
||||
0 => 6,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
//! PCI device Information
|
||||
|
||||
use super::cfg_space::PciDeviceCommonCfgOffset;
|
||||
use crate::cfg_space::PciCommonCfgOffset;
|
||||
|
||||
/// PCI device Location
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
|
@ -129,23 +129,16 @@ pub struct PciDeviceId {
|
|||
pub subclass: u8,
|
||||
/// Specifies the type of function the device performs.
|
||||
pub class: u8,
|
||||
/// Subsystem Vendor ID
|
||||
pub subsystem_vendor_id: u16,
|
||||
/// Subsystem ID
|
||||
pub subsystem_id: u16,
|
||||
}
|
||||
|
||||
impl PciDeviceId {
|
||||
pub(super) fn new(location: PciDeviceLocation) -> Self {
|
||||
let vendor_id = location.read16(PciDeviceCommonCfgOffset::VendorId as u16);
|
||||
let device_id = location.read16(PciDeviceCommonCfgOffset::DeviceId as u16);
|
||||
let revision_id = location.read8(PciDeviceCommonCfgOffset::RevisionId as u16);
|
||||
let prog_if = location.read8(PciDeviceCommonCfgOffset::ClassCode as u16);
|
||||
let subclass = location.read8(PciDeviceCommonCfgOffset::ClassCode as u16 + 1);
|
||||
let class = location.read8(PciDeviceCommonCfgOffset::ClassCode as u16 + 2);
|
||||
let subsystem_vendor_id =
|
||||
location.read16(PciDeviceCommonCfgOffset::SubsystemVendorId as u16);
|
||||
let subsystem_id = location.read16(PciDeviceCommonCfgOffset::SubsystemId as u16);
|
||||
let vendor_id = location.read16(PciCommonCfgOffset::VendorId as u16);
|
||||
let device_id = location.read16(PciCommonCfgOffset::DeviceId as u16);
|
||||
let revision_id = location.read8(PciCommonCfgOffset::RevisionId as u16);
|
||||
let prog_if = location.read8(PciCommonCfgOffset::ProgIf as u16);
|
||||
let subclass = location.read8(PciCommonCfgOffset::SubclassCode as u16);
|
||||
let class = location.read8(PciCommonCfgOffset::BaseClassCode as u16);
|
||||
Self {
|
||||
vendor_id,
|
||||
device_id,
|
||||
|
|
@ -153,8 +146,6 @@ impl PciDeviceId {
|
|||
prog_if,
|
||||
subclass,
|
||||
class,
|
||||
subsystem_vendor_id,
|
||||
subsystem_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue