mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-23 01:13:23 +00:00
Remove jinux-pci and hide PCI ports
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
b3799ff9c7
commit
df42397cea
19
Cargo.lock
generated
19
Cargo.lock
generated
@ -659,7 +659,6 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"component",
|
||||
"jinux-frame",
|
||||
"jinux-pci",
|
||||
"jinux-util",
|
||||
"jinux-virtio",
|
||||
"lazy_static",
|
||||
@ -716,7 +715,6 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"component",
|
||||
"jinux-frame",
|
||||
"jinux-pci",
|
||||
"jinux-rights",
|
||||
"jinux-util",
|
||||
"jinux-virtio",
|
||||
@ -732,7 +730,6 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"component",
|
||||
"jinux-frame",
|
||||
"jinux-pci",
|
||||
"jinux-rights",
|
||||
"jinux-util",
|
||||
"jinux-virtio",
|
||||
@ -742,21 +739,6 @@ dependencies = [
|
||||
"spin 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinux-pci"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"component",
|
||||
"jinux-frame",
|
||||
"jinux-rights",
|
||||
"jinux-util",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"pod",
|
||||
"spin 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinux-rights"
|
||||
version = "0.1.0"
|
||||
@ -847,7 +829,6 @@ dependencies = [
|
||||
"component",
|
||||
"int-to-c-enum",
|
||||
"jinux-frame",
|
||||
"jinux-pci",
|
||||
"jinux-rights",
|
||||
"jinux-util",
|
||||
"log",
|
||||
|
@ -22,7 +22,6 @@ jinux-framebuffer = { path = "services/comps/framebuffer" }
|
||||
members = [
|
||||
"build",
|
||||
"framework/jinux-frame",
|
||||
"services/comps/pci",
|
||||
"services/comps/virtio",
|
||||
"services/comps/input",
|
||||
"services/comps/block",
|
||||
|
@ -1,7 +1,6 @@
|
||||
# template
|
||||
[components]
|
||||
std = { name = "jinux-std" }
|
||||
pci = { name = "jinux-pci" }
|
||||
virtio = { name = "jinux-virtio" }
|
||||
input = { name = "jinux-input" }
|
||||
block = { name = "jinux-block" }
|
||||
|
@ -3,5 +3,4 @@
|
||||
|
||||
pub mod cmos;
|
||||
pub mod io_port;
|
||||
pub mod pci;
|
||||
pub mod serial;
|
||||
|
@ -5,6 +5,7 @@ pub mod iommu;
|
||||
pub(crate) mod irq;
|
||||
mod kernel;
|
||||
pub(crate) mod mm;
|
||||
pub(crate) mod pci;
|
||||
pub(crate) mod timer;
|
||||
|
||||
use alloc::fmt;
|
||||
|
@ -1,7 +1,6 @@
|
||||
//! PCI bus io port
|
||||
|
||||
use super::io_port::IoPort;
|
||||
use super::io_port::{ReadWriteAccess, WriteOnlyAccess};
|
||||
use super::device::io_port::{IoPort, ReadWriteAccess, WriteOnlyAccess};
|
||||
|
||||
pub static PCI_ADDRESS_PORT: IoPort<u32, WriteOnlyAccess> = unsafe { IoPort::new(0x0CF8) };
|
||||
pub static PCI_DATA_PORT: IoPort<u32, ReadWriteAccess> = unsafe { IoPort::new(0x0CFC) };
|
@ -1,6 +1,6 @@
|
||||
use core::iter;
|
||||
|
||||
use crate::arch::device::pci::{PCI_ADDRESS_PORT, PCI_DATA_PORT};
|
||||
use crate::arch::pci::{PCI_ADDRESS_PORT, PCI_DATA_PORT};
|
||||
|
||||
use super::cfg_space::PciDeviceCommonCfgOffset;
|
||||
|
||||
|
@ -9,7 +9,6 @@ edition = "2021"
|
||||
bitflags = "1.3"
|
||||
spin = "0.9.4"
|
||||
jinux-frame = { path = "../../../framework/jinux-frame" }
|
||||
jinux-pci = { path = "../pci" }
|
||||
jinux-virtio = { path = "../virtio" }
|
||||
jinux-util = { path = "../../libs/jinux-util" }
|
||||
component = { path = "../../libs/comp-sys/component" }
|
||||
|
@ -9,7 +9,6 @@ edition = "2021"
|
||||
bitflags = "1.3"
|
||||
spin = "0.9.4"
|
||||
jinux-frame = { path = "../../../framework/jinux-frame" }
|
||||
jinux-pci = { path = "../pci" }
|
||||
jinux-virtio = { path = "../virtio" }
|
||||
jinux-util = { path = "../../libs/jinux-util" }
|
||||
jinux-rights = { path = "../../libs/jinux-rights" }
|
||||
|
@ -10,7 +10,6 @@ component = { path = "../../libs/comp-sys/component" }
|
||||
jinux-frame = { path = "../../../framework/jinux-frame" }
|
||||
jinux-virtio = { path = "../virtio" }
|
||||
jinux-util = { path = "../../libs/jinux-util" }
|
||||
jinux-pci = { path = "../pci" }
|
||||
jinux-rights = { path = "../../libs/jinux-rights" }
|
||||
spin = "0.9.4"
|
||||
ringbuf = { version = "0.3.2", default-features = false, features = ["alloc"] }
|
||||
|
@ -1,22 +0,0 @@
|
||||
[package]
|
||||
name = "jinux-pci"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.3"
|
||||
spin = "0.9.4"
|
||||
jinux-frame = { path = "../../../framework/jinux-frame" }
|
||||
jinux-util = { path = "../../libs/jinux-util" }
|
||||
jinux-rights = { path = "../../libs/jinux-rights" }
|
||||
pod = { git = "https://github.com/jinzhao-dev/pod", rev = "71e59ec" }
|
||||
component = { path = "../../libs/comp-sys/component" }
|
||||
log = "0.4"
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1.0"
|
||||
features = ["spin_no_std"]
|
||||
|
||||
[features]
|
@ -1,23 +0,0 @@
|
||||
use crate::util::CSpaceAccessMethod;
|
||||
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct CapabilityEXPData {
|
||||
interrupt_message_number: u16,
|
||||
slot_implemented: u16,
|
||||
device_port_type: u16,
|
||||
cap_version: u16,
|
||||
}
|
||||
|
||||
impl CapabilityEXPData {
|
||||
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||
let am = CSpaceAccessMethod::IO;
|
||||
let cap = am.read16(loc, cap_ptr + 0x2);
|
||||
Self {
|
||||
interrupt_message_number: (cap >> 9) & 0b11111,
|
||||
slot_implemented: (cap >> 8) & 0x1,
|
||||
device_port_type: (cap >> 4) & 0xf,
|
||||
cap_version: cap & 0xf,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
//! This mod is used in frame to do device initialization
|
||||
use crate::util::CSpaceAccessMethod;
|
||||
use alloc::vec::Vec;
|
||||
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||
|
||||
use self::{
|
||||
exp::CapabilityEXPData, msi::CapabilityMSIData, msix::CapabilityMSIXData, pm::CapabilityPMData,
|
||||
sata::CapabilitySATAData, vendor::CapabilityVNDRData,
|
||||
};
|
||||
|
||||
use super::PCI_CAP_PTR;
|
||||
|
||||
pub mod exp;
|
||||
pub mod msi;
|
||||
pub mod msix;
|
||||
pub mod pm;
|
||||
pub mod sata;
|
||||
pub mod vendor;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum CapabilityData {
|
||||
/// Id:0x01, Power Management
|
||||
PM(CapabilityPMData),
|
||||
/// Id:0x02, Accelerated Graphics Part
|
||||
AGP,
|
||||
/// Id:0x03, Vital Product Data
|
||||
VPD,
|
||||
/// Id:0x04, Slot Identification
|
||||
SLOTID,
|
||||
/// Id:0x05, Message Signalled Interrupts
|
||||
MSI(CapabilityMSIData),
|
||||
/// Id:0x06, CompactPCI HotSwap
|
||||
CHSWP,
|
||||
/// Id:0x07, PCI-X
|
||||
PCIX,
|
||||
/// Id:0x08, HyperTransport
|
||||
HP,
|
||||
/// Id:0x09, Vendor-Specific
|
||||
VNDR(CapabilityVNDRData),
|
||||
/// Id:0x0A, Debug port
|
||||
DBG,
|
||||
/// Id:0x0B, CompactPCI Central Resource Control
|
||||
CCRC,
|
||||
/// Id:0x0C, PCI Standard Hot-Plug Controller
|
||||
SHPC,
|
||||
/// Id:0x0D, Bridge subsystem vendor/device ID
|
||||
SSVID,
|
||||
/// Id:0x0R, AGP Target PCI-PCI bridge
|
||||
AGP3,
|
||||
/// Id:0x0F, Secure Device
|
||||
SECDEV,
|
||||
/// Id:0x10, PCI Express
|
||||
EXP(CapabilityEXPData),
|
||||
/// Id:0x11, MSI-X
|
||||
MSIX(CapabilityMSIXData),
|
||||
/// Id:0x12, SATA Data/Index Conf
|
||||
SATA(CapabilitySATAData),
|
||||
/// Id:0x13, PCI Advanced Features
|
||||
AF,
|
||||
/// Id:0x14, Enhanced Allocation
|
||||
EA,
|
||||
/// Id:?, Unknown
|
||||
Unknown(u8),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Capability {
|
||||
pub cap_ptr: u16,
|
||||
pub data: CapabilityData,
|
||||
}
|
||||
|
||||
impl Capability {
|
||||
/// get the capabilities of one device
|
||||
pub fn device_capabilities(loc: PciDeviceLocation) -> Vec<Self> {
|
||||
let mut capabilities = Vec::new();
|
||||
let am = CSpaceAccessMethod::IO;
|
||||
let mut cap_ptr = am.read8(loc, PCI_CAP_PTR) as u16;
|
||||
while cap_ptr > 0 {
|
||||
let cap_vndr = am.read8(loc, cap_ptr);
|
||||
let data = match cap_vndr {
|
||||
0x01 => CapabilityData::PM(CapabilityPMData::new(loc, cap_ptr)),
|
||||
0x02 => CapabilityData::AGP,
|
||||
0x03 => CapabilityData::VPD,
|
||||
0x04 => CapabilityData::SLOTID,
|
||||
0x05 => CapabilityData::MSI(CapabilityMSIData::new(loc, cap_ptr)),
|
||||
0x06 => CapabilityData::CHSWP,
|
||||
0x07 => CapabilityData::PCIX,
|
||||
0x08 => CapabilityData::HP,
|
||||
0x09 => CapabilityData::VNDR(CapabilityVNDRData::new(loc, cap_ptr)),
|
||||
0x0A => CapabilityData::DBG,
|
||||
0x0B => CapabilityData::CCRC,
|
||||
0x0C => CapabilityData::SHPC,
|
||||
0x0D => CapabilityData::SSVID,
|
||||
0x0E => CapabilityData::AGP3,
|
||||
0x0F => CapabilityData::SECDEV,
|
||||
0x10 => CapabilityData::EXP(CapabilityEXPData::new(loc, cap_ptr)),
|
||||
0x11 => CapabilityData::MSIX(CapabilityMSIXData::new(loc, cap_ptr)),
|
||||
0x12 => CapabilityData::SATA(CapabilitySATAData::new(loc, cap_ptr)),
|
||||
0x13 => CapabilityData::AF,
|
||||
0x14 => CapabilityData::EA,
|
||||
_ => CapabilityData::Unknown(cap_vndr),
|
||||
};
|
||||
capabilities.push(Self {
|
||||
cap_ptr: cap_ptr,
|
||||
data: data,
|
||||
});
|
||||
cap_ptr = am.read8(loc, cap_ptr + 1) as u16;
|
||||
}
|
||||
capabilities
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
use crate::util::CSpaceAccessMethod;
|
||||
use bitflags::bitflags;
|
||||
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||
bitflags! {
|
||||
pub struct CapabilityMSIMessageControl: u16 {
|
||||
const ADDR64_CAPABLE = 1 << 7;
|
||||
const MULTIPLE_MESSAGE_ENABLE_2 = 1 << 4;
|
||||
const MULTIPLE_MESSAGE_ENABLE_4 = 2 << 4;
|
||||
const MULTIPLE_MESSAGE_ENABLE_8 = 3 << 4;
|
||||
const MULTIPLE_MESSAGE_ENABLE_16 = 4 << 4;
|
||||
const MULTIPLE_MESSAGE_ENABLE_32 = 5 << 4;
|
||||
const MULTIPLE_MESSAGE_CAPABLE_2 = 1 << 1;
|
||||
const MULTIPLE_MESSAGE_CAPABLE_4 = 2 << 1;
|
||||
const MULTIPLE_MESSAGE_CAPABLE_8 = 3 << 1;
|
||||
const MULTIPLE_MESSAGE_CAPABLE_16 = 4 << 1;
|
||||
const MULTIPLE_MESSAGE_CAPABLE_32 = 5 << 1;
|
||||
const ENABLE = 1 << 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct CapabilityMSIData {
|
||||
message_control: CapabilityMSIMessageControl,
|
||||
message_address: u64,
|
||||
message_data: u16,
|
||||
}
|
||||
|
||||
impl CapabilityMSIData {
|
||||
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||
let am = CSpaceAccessMethod::IO;
|
||||
let message_control =
|
||||
CapabilityMSIMessageControl::from_bits_truncate(am.read16(loc, cap_ptr + 0x02));
|
||||
let (addr, data) = if message_control.contains(CapabilityMSIMessageControl::ADDR64_CAPABLE)
|
||||
{
|
||||
// 64bit
|
||||
let lo = am.read32(loc, cap_ptr + 0x04) as u64;
|
||||
let hi = am.read32(loc, cap_ptr + 0x08) as u64;
|
||||
let data = am.read16(loc, cap_ptr + 0x0C);
|
||||
((hi << 32) | lo, data)
|
||||
} else {
|
||||
// 32bit
|
||||
let addr = am.read32(loc, cap_ptr + 0x04) as u64;
|
||||
let data = am.read16(loc, cap_ptr + 0x0C);
|
||||
(addr, data)
|
||||
};
|
||||
Self {
|
||||
message_control: message_control,
|
||||
message_address: addr,
|
||||
message_data: data,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
use crate::util::CSpaceAccessMethod;
|
||||
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct CapabilityMSIXData {
|
||||
pub message_control: u16,
|
||||
pub table_info: u32,
|
||||
pub pba_info: u32,
|
||||
}
|
||||
|
||||
impl CapabilityMSIXData {
|
||||
pub fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||
let am = CSpaceAccessMethod::IO;
|
||||
Self {
|
||||
message_control: am.read16(loc, cap_ptr + 2),
|
||||
table_info: am.read32(loc, cap_ptr + 4),
|
||||
pba_info: am.read32(loc, cap_ptr + 8),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
use crate::util::CSpaceAccessMethod;
|
||||
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct CapabilityPMData {
|
||||
pub pme_support: u32,
|
||||
pub d2_support: u32,
|
||||
pub d1_support: u32,
|
||||
pub aux_current: u32,
|
||||
pub dsi: u32,
|
||||
pub pme_clock: u32,
|
||||
pub version: u32,
|
||||
}
|
||||
|
||||
impl CapabilityPMData {
|
||||
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||
let am = CSpaceAccessMethod::IO;
|
||||
let cap = am.read32(loc, cap_ptr + 0x4);
|
||||
Self {
|
||||
pme_support: cap >> 27,
|
||||
d2_support: (cap >> 26) & 0x1,
|
||||
d1_support: (cap >> 25) & 0x1,
|
||||
aux_current: (cap >> 22) & 0x7,
|
||||
dsi: (cap >> 21) & 0x1,
|
||||
pme_clock: (cap >> 19) & 0x1,
|
||||
version: (cap >> 16) & 0x7,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
use crate::util::CSpaceAccessMethod;
|
||||
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct CapabilitySATAData {
|
||||
major_revision: u32,
|
||||
minor_revision: u32,
|
||||
bar_offset: u32,
|
||||
bar_location: u32,
|
||||
}
|
||||
|
||||
impl CapabilitySATAData {
|
||||
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||
let am = CSpaceAccessMethod::IO;
|
||||
let sata_cr0 = am.read32(loc, cap_ptr);
|
||||
let sata_cr1 = am.read32(loc, cap_ptr + 0x4);
|
||||
Self {
|
||||
major_revision: (sata_cr0 >> 20) & 0xf,
|
||||
minor_revision: (sata_cr0 >> 16) & 0xf,
|
||||
bar_offset: (sata_cr1 >> 4) & 0xfffff,
|
||||
bar_location: sata_cr1 & 0xf,
|
||||
}
|
||||
}
|
||||
}
|
28
services/comps/pci/src/capability/vendor/mod.rs
vendored
28
services/comps/pci/src/capability/vendor/mod.rs
vendored
@ -1,28 +0,0 @@
|
||||
pub mod virtio;
|
||||
|
||||
use virtio::CapabilityVirtioData;
|
||||
|
||||
use crate::util::CSpaceAccessMethod;
|
||||
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum CapabilityVNDRData {
|
||||
/// Virtio
|
||||
VIRTIO(CapabilityVirtioData),
|
||||
}
|
||||
|
||||
impl CapabilityVNDRData {
|
||||
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||
let am = CSpaceAccessMethod::IO;
|
||||
let vid = am.read16(loc, 0);
|
||||
match vid {
|
||||
0x1af4 => Self::VIRTIO(CapabilityVirtioData::new(loc, cap_ptr)),
|
||||
_ => {
|
||||
panic!(
|
||||
"unsupport vendor-specific capability, deivce vendor id:{}",
|
||||
vid
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
use crate::util::CSpaceAccessMethod;
|
||||
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct CapabilityVirtioData {
|
||||
pub cfg_type: u8,
|
||||
pub bar: u8,
|
||||
pub offset: u32,
|
||||
pub length: u32,
|
||||
pub option: Option<u32>,
|
||||
}
|
||||
|
||||
impl CapabilityVirtioData {
|
||||
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||
let am = CSpaceAccessMethod::IO;
|
||||
let cap_len = am.read8(loc, cap_ptr + 2);
|
||||
let option = if cap_len > 0x10 {
|
||||
Some(am.read32(loc, cap_ptr + 16))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Self {
|
||||
cfg_type: am.read8(loc, cap_ptr + 3),
|
||||
bar: am.read8(loc, cap_ptr + 4),
|
||||
offset: am.read32(loc, cap_ptr + 8),
|
||||
length: am.read32(loc, cap_ptr + 12),
|
||||
option: option,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
//! The pci of jinux
|
||||
#![no_std]
|
||||
#![forbid(unsafe_code)]
|
||||
#![allow(dead_code)]
|
||||
pub mod capability;
|
||||
pub mod msix;
|
||||
pub mod util;
|
||||
extern crate alloc;
|
||||
|
||||
use component::init_component;
|
||||
use component::ComponentInitError;
|
||||
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||
use jinux_frame::sync::Mutex;
|
||||
use spin::Once;
|
||||
use util::CSpaceAccessMethod;
|
||||
|
||||
pub use crate::util::PciDevice;
|
||||
|
||||
pub const PCI_COMMAND: u16 = 0x04;
|
||||
pub const PCI_BAR: u16 = 0x10;
|
||||
pub const PCI_CAP_PTR: u16 = 0x34;
|
||||
pub const PCI_INTERRUPT_LINE: u16 = 0x3c;
|
||||
pub const PCI_INTERRUPT_PIN: u16 = 0x3d;
|
||||
|
||||
pub const PCI_MSIX_CTRL_CAP: u16 = 0x00;
|
||||
pub const PCI_MSIX_TABLE: u16 = 0x04;
|
||||
pub const PCI_MSIX_PBA: u16 = 0x08;
|
||||
|
||||
pub const PCI_CAP_ID_MSI: u8 = 0x05;
|
||||
|
||||
pub static PCI_COMPONENT: Once<PCIComponent> = Once::new();
|
||||
|
||||
#[init_component]
|
||||
fn pci_component_init() -> Result<(), ComponentInitError> {
|
||||
let a = PCIComponent::init()?;
|
||||
PCI_COMPONENT.call_once(|| a);
|
||||
Ok(())
|
||||
}
|
||||
pub struct PCIComponent {
|
||||
pci_device: Mutex<Vec<Arc<PciDevice>>>,
|
||||
}
|
||||
|
||||
impl PCIComponent {
|
||||
pub fn init() -> Result<Self, ComponentInitError> {
|
||||
let mut devices = Vec::new();
|
||||
for location in PciDeviceLocation::all() {
|
||||
let Some(device) = util::find_device(location, CSpaceAccessMethod::IO) else {
|
||||
continue;
|
||||
};
|
||||
log::info!(
|
||||
"pci: {:02x}:{:02x}.{} {:#x} {:#x} ({} {}) command: {:?} status: {:?} irq: {}:{:?}",
|
||||
device.loc.bus,
|
||||
device.loc.device,
|
||||
device.loc.function,
|
||||
device.id.vendor_id,
|
||||
device.id.device_id,
|
||||
device.id.class,
|
||||
device.id.subclass,
|
||||
device.command,
|
||||
device.status,
|
||||
device.pic_interrupt_line,
|
||||
device.interrupt_pin
|
||||
);
|
||||
devices.push(Arc::new(device));
|
||||
}
|
||||
Ok(Self {
|
||||
pci_device: Mutex::new(devices),
|
||||
})
|
||||
}
|
||||
|
||||
pub const fn name() -> &'static str {
|
||||
"PCI"
|
||||
}
|
||||
// 0~65535
|
||||
pub const fn priority() -> u16 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl PCIComponent {
|
||||
pub fn get_pci_devices(self: &Self, index: usize) -> Option<Arc<PciDevice>> {
|
||||
self.pci_device.lock().get(index).cloned()
|
||||
}
|
||||
|
||||
pub fn device_amount(self: &Self) -> usize {
|
||||
self.pci_device.lock().len()
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
use core::mem::size_of;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use log::debug;
|
||||
use pod::Pod;
|
||||
|
||||
use crate::util::{CSpaceAccessMethod, BAR};
|
||||
|
||||
use super::capability::msix::CapabilityMSIXData;
|
||||
|
||||
use jinux_frame::{bus::pci::PciDeviceLocation, io_mem::IoMem, offset_of, trap::IrqAllocateHandle};
|
||||
use jinux_util::{field_ptr, safe_ptr::SafePtr};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MSIX {
|
||||
pub table_size: u16,
|
||||
pub table: Vec<MSIXEntry>,
|
||||
/// pointing to the Pending Table
|
||||
pub pba_paddr: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MSIXEntry {
|
||||
pub table_entry: SafePtr<MSIXTableEntry, IoMem>,
|
||||
pub irq_handle: IrqAllocateHandle,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Pod)]
|
||||
#[repr(C)]
|
||||
pub struct MSIXTableEntry {
|
||||
pub msg_addr: u32,
|
||||
pub msg_upper_addr: u32,
|
||||
pub msg_data: u32,
|
||||
pub vector_control: u32,
|
||||
}
|
||||
|
||||
impl MSIX {
|
||||
/// create a MSIX instance, it allocate the irq number automatically.
|
||||
pub fn new(
|
||||
cap: &CapabilityMSIXData,
|
||||
bars: [Option<BAR>; 6],
|
||||
loc: PciDeviceLocation,
|
||||
cap_ptr: u16,
|
||||
) -> Self {
|
||||
let table_info = cap.table_info;
|
||||
let pba_info = cap.pba_info;
|
||||
let table_size = (table_info & (0b11_1111_1111)) + 1;
|
||||
let table_bar_address;
|
||||
let pba_bar_address;
|
||||
match bars[(pba_info & 0b111) as usize].expect("MSIX cfg:table bar is none") {
|
||||
BAR::Memory(address, _, _, _) => {
|
||||
pba_bar_address = address;
|
||||
}
|
||||
BAR::IO(_, _) => {
|
||||
panic!("MSIX cfg:table bar is IO type")
|
||||
}
|
||||
}
|
||||
match bars[(table_info & 0b111) as usize].expect("MSIX cfg:table bar is none") {
|
||||
BAR::Memory(address, _, _, _) => {
|
||||
table_bar_address = address;
|
||||
}
|
||||
BAR::IO(_, _) => {
|
||||
panic!("MSIX cfg:table bar is IO type")
|
||||
}
|
||||
}
|
||||
// let pba_base_address = (pba_info >> 3 ) as u64 + pba_bar_address;
|
||||
// let table_base_address = (table_info >>3 ) as u64 + table_bar_address;
|
||||
let pba_base_address = (pba_info & (!(0b111 as u32))) as u64 + pba_bar_address;
|
||||
let table_base_address = (table_info & (!(0b111 as u32))) as u64 + table_bar_address;
|
||||
debug!("MSIX table size:{}, pba_info:{:x}, table_info:{:x}, pba_address:{:x}, table_address:{:x}",
|
||||
table_size,pba_info,table_info,pba_base_address,table_base_address);
|
||||
let mut cap = Self {
|
||||
table_size: table_size as u16,
|
||||
table: Vec::new(),
|
||||
pba_paddr: pba_base_address,
|
||||
};
|
||||
// enable MSI-X disable INTx
|
||||
let am = CSpaceAccessMethod::IO;
|
||||
debug!("command before:{:x}", am.read16(loc, crate::PCI_COMMAND));
|
||||
am.write16(
|
||||
loc,
|
||||
crate::PCI_COMMAND,
|
||||
am.read16(loc, crate::PCI_COMMAND) | 0x40f,
|
||||
);
|
||||
debug!("command after:{:x}", am.read16(loc, crate::PCI_COMMAND));
|
||||
let message_control = am.read16(loc, cap_ptr + 2) | 0x8000;
|
||||
am.write16(loc, cap_ptr + 2, message_control);
|
||||
let mut table_iter: SafePtr<MSIXTableEntry, IoMem> = SafePtr::new(
|
||||
IoMem::new(
|
||||
table_base_address as usize
|
||||
..table_base_address as usize
|
||||
+ (size_of::<MSIXTableEntry>() * table_size as usize),
|
||||
)
|
||||
.unwrap(),
|
||||
0,
|
||||
);
|
||||
for _ in 0..table_size {
|
||||
// local APIC address: 0xFEE0_0000
|
||||
field_ptr!(&table_iter, MSIXTableEntry, msg_addr)
|
||||
.write(&0xFEE0_0000u32)
|
||||
.unwrap();
|
||||
field_ptr!(&table_iter, MSIXTableEntry, msg_upper_addr)
|
||||
.write(&0u32)
|
||||
.unwrap();
|
||||
// allocate irq number
|
||||
let handle = jinux_frame::trap::allocate_irq().expect("not enough irq");
|
||||
field_ptr!(&table_iter, MSIXTableEntry, msg_data)
|
||||
.write(&(handle.num() as u32))
|
||||
.unwrap();
|
||||
field_ptr!(&table_iter, MSIXTableEntry, vector_control)
|
||||
.write(&0u32)
|
||||
.unwrap();
|
||||
cap.table.push(MSIXEntry {
|
||||
table_entry: table_iter.clone(),
|
||||
irq_handle: handle,
|
||||
});
|
||||
table_iter.add(1);
|
||||
}
|
||||
cap
|
||||
}
|
||||
}
|
@ -1,498 +0,0 @@
|
||||
extern crate jinux_frame;
|
||||
use crate::capability::Capability;
|
||||
use alloc::vec::Vec;
|
||||
use bitflags::bitflags;
|
||||
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||
|
||||
pub enum PCIDeviceCommonCfgOffset {
|
||||
VendorId = 0x00,
|
||||
DeviceId = 0x02,
|
||||
Command = 0x04,
|
||||
Status = 0x06,
|
||||
RevisionId = 0x08,
|
||||
ClassCode = 0x09,
|
||||
CacheLineSize = 0x0C,
|
||||
LatencyTimer = 0x0D,
|
||||
HeaderType = 0x0E,
|
||||
BIST = 0x0F,
|
||||
BAR0 = 0x10,
|
||||
BAR1 = 0x14,
|
||||
BAR2 = 0x18,
|
||||
BAR3 = 0x1C,
|
||||
BAR4 = 0x20,
|
||||
BAR5 = 0x24,
|
||||
CardbusCisPtr = 0x28,
|
||||
SubsystemVendorId = 0x2C,
|
||||
SubsystemId = 0x2E,
|
||||
XROMBAR = 0x30,
|
||||
CapabilitiesPointer = 0x34,
|
||||
InterruptLine = 0x3C,
|
||||
InterruptPin = 0x3D,
|
||||
MinGrant = 0x3E,
|
||||
MaxLatency = 0x3F,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum CSpaceAccessMethod {
|
||||
// The legacy, deprecated (as of PCI 2.0) IO-range method.
|
||||
// Until/unless there is a relevant platform that requires this, leave it out.
|
||||
// IO_Mechanism_2
|
||||
/// The legacy (pre-PCIe) 2-IO port method as specified on page 50 of PCI Local Bus
|
||||
/// Specification 3.0.
|
||||
IO,
|
||||
// PCIe memory-mapped configuration space access
|
||||
//MemoryMapped(*mut u8),
|
||||
}
|
||||
|
||||
// All IO-bus ops are 32-bit, we mask and shift to get the values we want.
|
||||
|
||||
impl CSpaceAccessMethod {
|
||||
pub fn read8(self, loc: PciDeviceLocation, offset: u16) -> u8 {
|
||||
let val = self.read32(loc, offset & 0b11111100);
|
||||
((val >> ((offset as usize & 0b11) << 3)) & 0xFF) as u8
|
||||
}
|
||||
|
||||
/// Returns a value in native endian.
|
||||
pub fn read16(self, loc: PciDeviceLocation, offset: u16) -> u16 {
|
||||
let val = self.read32(loc, offset & 0b11111100);
|
||||
((val >> ((offset as usize & 0b10) << 3)) & 0xFFFF) as u16
|
||||
}
|
||||
|
||||
/// Returns a value in native endian.
|
||||
pub fn read32(self, loc: PciDeviceLocation, offset: u16) -> u32 {
|
||||
debug_assert!(
|
||||
(offset & 0b11) == 0,
|
||||
"misaligned PCI configuration dword u32 read"
|
||||
);
|
||||
match self {
|
||||
CSpaceAccessMethod::IO => {
|
||||
jinux_frame::arch::x86::device::pci::PCI_ADDRESS_PORT
|
||||
.write(loc.encode_as_x86_address_value() | ((offset as u32) & 0b11111100));
|
||||
jinux_frame::arch::x86::device::pci::PCI_DATA_PORT
|
||||
.read()
|
||||
.to_le()
|
||||
} //MemoryMapped(ptr) => {
|
||||
// // FIXME: Clarify whether the rules for GEP/GEPi forbid using regular .offset() here.
|
||||
// ::core::intrinsics::volatile_load(::core::intrinsics::arith_offset(ptr, offset as usize))
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write8(self, loc: PciDeviceLocation, offset: u16, val: u8) {
|
||||
let old = self.read32(loc, offset & (0xFFFC));
|
||||
let dest = offset as usize & 0b11 << 3;
|
||||
let mask = (0xFF << dest) as u32;
|
||||
self.write32(
|
||||
loc,
|
||||
offset & (0xFFFC),
|
||||
((val as u32) << dest | (old & !mask)).to_le(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Converts val to little endian before writing.
|
||||
pub fn write16(self, loc: PciDeviceLocation, offset: u16, val: u16) {
|
||||
let old = self.read32(loc, offset & (0xFFFC));
|
||||
let dest = offset as usize & 0b10 << 3;
|
||||
let mask = (0xFFFF << dest) as u32;
|
||||
self.write32(
|
||||
loc,
|
||||
offset & (0xFFFC),
|
||||
((val as u32) << dest | (old & !mask)).to_le(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Takes a value in native endian, converts it to little-endian, and writes it to the PCI
|
||||
/// device configuration space at register `offset`.
|
||||
pub fn write32(self, loc: PciDeviceLocation, offset: u16, val: u32) {
|
||||
debug_assert!(
|
||||
(offset & 0b11) == 0,
|
||||
"misaligned PCI configuration dword u32 read"
|
||||
);
|
||||
match self {
|
||||
CSpaceAccessMethod::IO => {
|
||||
jinux_frame::arch::x86::device::pci::PCI_ADDRESS_PORT
|
||||
.write(loc.encode_as_x86_address_value() | (offset as u32 & 0b11111100));
|
||||
jinux_frame::arch::x86::device::pci::PCI_DATA_PORT.write(val.to_le())
|
||||
} //MemoryMapped(ptr) => {
|
||||
// // FIXME: Clarify whether the rules for GEP/GEPi forbid using regular .offset() here.
|
||||
// ::core::intrinsics::volatile_load(::core::intrinsics::arith_offset(ptr, offset as usize))
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Identifier {
|
||||
pub vendor_id: u16,
|
||||
pub device_id: u16,
|
||||
pub revision_id: u8,
|
||||
pub prog_if: u8,
|
||||
pub class: u8,
|
||||
pub subclass: u8,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct Command: u16 {
|
||||
const IO_SPACE = 1 << 0;
|
||||
const MEMORY_SPACE = 1 << 1;
|
||||
const BUS_MASTER = 1 << 2;
|
||||
const SPECIAL_CYCLES = 1 << 3;
|
||||
const MWI_ENABLE = 1 << 4;
|
||||
const VGA_PALETTE_SNOOP = 1 << 5;
|
||||
const PARITY_ERROR_RESPONSE = 1 << 6;
|
||||
const STEPPING_CONTROL = 1 << 7;
|
||||
const SERR_ENABLE = 1 << 8;
|
||||
const FAST_BACK_TO_BACK_ENABLE = 1 << 9;
|
||||
const INTERRUPT_DISABLE = 1 << 10;
|
||||
const RESERVED_11 = 1 << 11;
|
||||
const RESERVED_12 = 1 << 12;
|
||||
const RESERVED_13 = 1 << 13;
|
||||
const RESERVED_14 = 1 << 14;
|
||||
const RESERVED_15 = 1 << 15;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct Status: u16 {
|
||||
const RESERVED_0 = 1 << 0;
|
||||
const RESERVED_1 = 1 << 1;
|
||||
const RESERVED_2 = 1 << 2;
|
||||
const INTERRUPT_STATUS = 1 << 3;
|
||||
const CAPABILITIES_LIST = 1 << 4;
|
||||
const MHZ66_CAPABLE = 1 << 5;
|
||||
const RESERVED_6 = 1 << 6;
|
||||
const FAST_BACK_TO_BACK_CAPABLE = 1 << 7;
|
||||
const MASTER_DATA_PARITY_ERROR = 1 << 8;
|
||||
const DEVSEL_MEDIUM_TIMING = 1 << 9;
|
||||
const DEVSEL_SLOW_TIMING = 1 << 10;
|
||||
const SIGNALED_TARGET_ABORT = 1 << 11;
|
||||
const RECEIVED_TARGET_ABORT = 1 << 12;
|
||||
const RECEIVED_MASTER_ABORT = 1 << 13;
|
||||
const SIGNALED_SYSTEM_ERROR = 1 << 14;
|
||||
const DETECTED_PARITY_ERROR = 1 << 15;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct BridgeControl: u16 {
|
||||
const PARITY_ERROR_RESPONSE_ENABLE = 1 << 0;
|
||||
const SERR_ENABLE = 1 << 1;
|
||||
const ISA_ENABLE = 1 << 2;
|
||||
const VGA_ENABLE = 1 << 3;
|
||||
const RESERVED_4 = 1 << 4;
|
||||
const MASTER_ABORT_MODE = 1 << 5;
|
||||
const SECONDARY_BUS_RESET = 1 << 6;
|
||||
const FAST_BACK_TO_BACK_ENABLE = 1 << 7;
|
||||
const PRIMARY_DISCARD_TIMER = 1 << 8;
|
||||
const SECONDARY_DISCARD_TIMER = 1 << 9;
|
||||
const DISCARD_TIMER_STATUS = 1 << 10;
|
||||
const DISCARD_TIMER_SERR_ENABLED = 1 << 11;
|
||||
const RESERVED_12 = 1 << 12;
|
||||
const RESERVED_13 = 1 << 13;
|
||||
const RESERVED_14 = 1 << 14;
|
||||
const RESERVED_15 = 1 << 15;
|
||||
}
|
||||
}
|
||||
|
||||
/// A device on the PCI bus.
|
||||
///
|
||||
/// Although accessing configuration space may be expensive, it is not cached.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct PciDevice {
|
||||
pub loc: PciDeviceLocation,
|
||||
pub id: Identifier,
|
||||
pub command: Command,
|
||||
pub status: Status,
|
||||
pub cache_line_size: u8,
|
||||
pub latency_timer: u8,
|
||||
pub multifunction: bool,
|
||||
pub bist_capable: bool,
|
||||
pub bars: [Option<BAR>; 6],
|
||||
pub kind: DeviceKind,
|
||||
pub pic_interrupt_line: u8,
|
||||
pub interrupt_pin: Option<InterruptPin>,
|
||||
pub cspace_access_method: CSpaceAccessMethod,
|
||||
pub capabilities: Vec<Capability>,
|
||||
}
|
||||
|
||||
impl PciDevice {
|
||||
/// set the status bits
|
||||
pub fn set_status_bits(&self, status: Status) {
|
||||
let am = CSpaceAccessMethod::IO;
|
||||
let status = am.read16(self.loc, 0x06) | status.bits;
|
||||
am.write16(self.loc, 0x06, status)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum PCIScanError {}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Prefetchable {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Type {
|
||||
Bits32,
|
||||
Bits64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum DeviceKind {
|
||||
Device(DeviceDetails),
|
||||
PciBridge(PciBridgeDetails),
|
||||
CardbusBridge(CardbusBridgeDetails),
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct DeviceDetails {
|
||||
pub cardbus_cis_ptr: u32,
|
||||
pub subsystem_vendor_id: u16,
|
||||
pub subsystem_id: u16,
|
||||
pub expansion_rom_base_addr: u32,
|
||||
pub min_grant: u8,
|
||||
pub max_latency: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct PciBridgeDetails {
|
||||
pub primary_bus: u8,
|
||||
pub secondary_bus: u8,
|
||||
pub subordinate_bus: u8,
|
||||
pub secondary_latency_timer: u8,
|
||||
pub io_base: u32,
|
||||
pub io_limit: u32,
|
||||
pub secondary_status: Status,
|
||||
pub mem_base: u32,
|
||||
pub mem_limit: u32,
|
||||
pub prefetchable_mem_base: u64,
|
||||
pub prefetchable_mem_limit: u64,
|
||||
pub expansion_rom_base_addr: u32,
|
||||
pub bridge_control: BridgeControl,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct CardbusBridgeDetails {
|
||||
pub socket_base_addr: u32,
|
||||
pub secondary_status: Status,
|
||||
pub pci_bus: u8,
|
||||
pub cardbus_bus: u8,
|
||||
pub subordinate_bus: u8,
|
||||
pub cardbus_latency_timer: u8,
|
||||
pub mem_base_0: u32,
|
||||
pub mem_limit_0: u32,
|
||||
pub mem_base_1: u32,
|
||||
pub mem_limit_1: u32,
|
||||
pub io_base_0: u32,
|
||||
pub io_limit_0: u32,
|
||||
pub io_base_1: u32,
|
||||
pub io_limit_1: u32,
|
||||
pub subsystem_device_id: u16,
|
||||
pub subsystem_vendor_id: u16,
|
||||
pub legacy_mode_base_addr: u32,
|
||||
pub bridge_control: BridgeControl,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum InterruptPin {
|
||||
INTA = 1,
|
||||
INTB,
|
||||
INTC,
|
||||
INTD,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum BAR {
|
||||
Memory(u64, u32, Prefetchable, Type),
|
||||
/// first element is address, second element is size
|
||||
IO(u32, u32),
|
||||
}
|
||||
|
||||
impl BAR {
|
||||
pub fn decode(
|
||||
loc: PciDeviceLocation,
|
||||
am: CSpaceAccessMethod,
|
||||
idx: u16,
|
||||
) -> (Option<BAR>, usize) {
|
||||
let raw = am.read32(loc, 16 + (idx << 2));
|
||||
am.write32(loc, 16 + (idx << 2), !0);
|
||||
let len_encoded = am.read32(loc, 16 + (idx << 2));
|
||||
am.write32(loc, 16 + (idx << 2), raw);
|
||||
if raw == 0 && len_encoded == 0 {
|
||||
return (None, idx as usize + 1);
|
||||
}
|
||||
if raw & 1 == 0 {
|
||||
let mut bits64 = false;
|
||||
let base: u64 = match (raw & 0b110) >> 1 {
|
||||
0 => (raw & !0xF) as u64,
|
||||
2 => {
|
||||
bits64 = true;
|
||||
((raw & !0xF) as u64) | ((am.read32(loc, 16 + ((idx + 1) << 2)) as u64) << 32)
|
||||
}
|
||||
_ => {
|
||||
debug_assert!(false, "bad type in memory BAR");
|
||||
return (None, idx as usize + 1);
|
||||
}
|
||||
};
|
||||
let len = !(len_encoded & !0xF).wrapping_add(1);
|
||||
(
|
||||
Some(BAR::Memory(
|
||||
base,
|
||||
len,
|
||||
if raw & 0b1000 == 0 {
|
||||
Prefetchable::No
|
||||
} else {
|
||||
Prefetchable::Yes
|
||||
},
|
||||
if bits64 { Type::Bits64 } else { Type::Bits32 },
|
||||
)),
|
||||
if bits64 { idx + 2 } else { idx + 1 } as usize,
|
||||
)
|
||||
} else {
|
||||
let len = !(len_encoded & !0x3) + 1;
|
||||
(Some(BAR::IO(raw & !0x3, len)), idx as usize + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn find_device(loc: PciDeviceLocation, am: CSpaceAccessMethod) -> Option<PciDevice> {
|
||||
// FIXME: it'd be more efficient to use read32 and decode separately.
|
||||
let vid = am.read16(loc, 0);
|
||||
if vid == 0xFFFF {
|
||||
return None;
|
||||
}
|
||||
let did = am.read16(loc, 2);
|
||||
let command = Command::from_bits_truncate(am.read16(loc, 4));
|
||||
let status = Status::from_bits_truncate(am.read16(loc, 6));
|
||||
let rid = am.read8(loc, 8);
|
||||
let prog_if = am.read8(loc, 9);
|
||||
let subclass = am.read8(loc, 10);
|
||||
let class = am.read8(loc, 11);
|
||||
let id = Identifier {
|
||||
vendor_id: vid,
|
||||
device_id: did,
|
||||
revision_id: rid,
|
||||
prog_if: prog_if,
|
||||
class: class,
|
||||
subclass: subclass,
|
||||
};
|
||||
let cache_line_size = am.read8(loc, 12);
|
||||
let latency_timer = am.read8(loc, 13);
|
||||
let bist_capable = am.read8(loc, 15) & (1 << 7) != 0;
|
||||
let hdrty_mf = am.read8(loc, 14);
|
||||
let hdrty = hdrty_mf & !(1 << 7);
|
||||
let mf = hdrty_mf & (1 << 7) != 0;
|
||||
let pic_interrupt_line = am.read8(loc, 0x3C);
|
||||
let interrupt_pin = match am.read8(loc, 0x3D) {
|
||||
1 => Some(InterruptPin::INTA),
|
||||
2 => Some(InterruptPin::INTB),
|
||||
3 => Some(InterruptPin::INTC),
|
||||
4 => Some(InterruptPin::INTD),
|
||||
_ => None,
|
||||
};
|
||||
let kind;
|
||||
let max;
|
||||
|
||||
match hdrty {
|
||||
0 => {
|
||||
max = 6;
|
||||
kind = DeviceKind::Device(DeviceDetails {
|
||||
cardbus_cis_ptr: am.read32(loc, 0x28),
|
||||
subsystem_vendor_id: am.read16(loc, 0x2C),
|
||||
subsystem_id: am.read16(loc, 0x2E),
|
||||
expansion_rom_base_addr: am.read32(loc, 0x30),
|
||||
min_grant: am.read8(loc, 0x3E),
|
||||
max_latency: am.read8(loc, 0x3F),
|
||||
});
|
||||
}
|
||||
1 => {
|
||||
max = 2;
|
||||
kind = DeviceKind::PciBridge(PciBridgeDetails {
|
||||
primary_bus: am.read8(loc, 0x18),
|
||||
secondary_bus: am.read8(loc, 0x19),
|
||||
subordinate_bus: am.read8(loc, 0x1a),
|
||||
secondary_latency_timer: am.read8(loc, 0x1b),
|
||||
secondary_status: Status::from_bits_truncate(am.read16(loc, 0x1e)),
|
||||
io_base: (am.read8(loc, 0x1c) as u32 & 0xF0) << 8
|
||||
| (am.read16(loc, 0x30) as u32) << 16,
|
||||
io_limit: 0xFFF
|
||||
| (am.read8(loc, 0x1d) as u32 & 0xF0) << 8
|
||||
| (am.read16(loc, 0x32) as u32) << 16,
|
||||
mem_base: (am.read16(loc, 0x20) as u32 & 0xFFF0) << 16,
|
||||
mem_limit: 0xFFFFF | (am.read16(loc, 0x22) as u32 & 0xFFF0) << 16,
|
||||
prefetchable_mem_base: (am.read16(loc, 0x24) as u64 & 0xFFF0) << 16
|
||||
| am.read32(loc, 0x28) as u64,
|
||||
prefetchable_mem_limit: 0xFFFFF
|
||||
| (am.read16(loc, 0x26) as u64 & 0xFFF0) << 16
|
||||
| am.read32(loc, 0x2c) as u64,
|
||||
expansion_rom_base_addr: am.read32(loc, 0x38),
|
||||
bridge_control: BridgeControl::from_bits_truncate(am.read16(loc, 0x3e)),
|
||||
});
|
||||
}
|
||||
2 => {
|
||||
max = 0;
|
||||
kind = DeviceKind::CardbusBridge(CardbusBridgeDetails {
|
||||
socket_base_addr: am.read32(loc, 0x10),
|
||||
secondary_status: Status::from_bits_truncate(am.read16(loc, 0x16)),
|
||||
pci_bus: am.read8(loc, 0x18),
|
||||
cardbus_bus: am.read8(loc, 0x19),
|
||||
subordinate_bus: am.read8(loc, 0x1a),
|
||||
cardbus_latency_timer: am.read8(loc, 0x1b),
|
||||
mem_base_0: am.read32(loc, 0x1c),
|
||||
mem_limit_0: am.read32(loc, 0x20),
|
||||
mem_base_1: am.read32(loc, 0x24),
|
||||
mem_limit_1: am.read32(loc, 0x28),
|
||||
io_base_0: am.read32(loc, 0x2c),
|
||||
io_limit_0: am.read32(loc, 0x30),
|
||||
io_base_1: am.read32(loc, 0x34),
|
||||
io_limit_1: am.read32(loc, 0x38),
|
||||
bridge_control: BridgeControl::from_bits_truncate(am.read16(loc, 0x3e)),
|
||||
subsystem_device_id: am.read16(loc, 0x40),
|
||||
subsystem_vendor_id: am.read16(loc, 0x42),
|
||||
legacy_mode_base_addr: am.read32(loc, 0x44),
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
max = 0;
|
||||
kind = DeviceKind::Unknown;
|
||||
debug_assert!(
|
||||
false,
|
||||
"pci: unknown device header type {} for {:?} {:?}",
|
||||
hdrty, loc, id
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let capabilities = if status.contains(Status::CAPABILITIES_LIST) {
|
||||
Capability::device_capabilities(loc)
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let mut bars = [None, None, None, None, None, None];
|
||||
let mut i = 0;
|
||||
while i < max {
|
||||
let (bar, next) = BAR::decode(loc, am, i as u16);
|
||||
bars[i] = bar;
|
||||
i = next;
|
||||
}
|
||||
|
||||
Some(PciDevice {
|
||||
loc: loc,
|
||||
id: id,
|
||||
command: command,
|
||||
status: status,
|
||||
cache_line_size: cache_line_size,
|
||||
latency_timer: latency_timer,
|
||||
multifunction: mf,
|
||||
bist_capable: bist_capable,
|
||||
bars: bars,
|
||||
kind: kind,
|
||||
pic_interrupt_line: pic_interrupt_line,
|
||||
interrupt_pin: interrupt_pin,
|
||||
cspace_access_method: am,
|
||||
capabilities: capabilities,
|
||||
})
|
||||
}
|
@ -11,7 +11,6 @@ spin = "0.9.4"
|
||||
bytes = { version = "1.4.0", default-features = false }
|
||||
align_ext = { path = "../../../framework/libs/align_ext" }
|
||||
jinux-frame = { path = "../../../framework/jinux-frame" }
|
||||
jinux-pci = { path = "../pci" }
|
||||
jinux-util = { path = "../../libs/jinux-util" }
|
||||
jinux-rights = { path = "../../libs/jinux-rights" }
|
||||
typeflags-util = { path = "../../libs/typeflags-util" }
|
||||
|
Reference in New Issue
Block a user