Remove jinux-pci and hide PCI ports

This commit is contained in:
Yuke Peng
2023-08-10 16:23:02 +08:00
committed by Tate, Hongliang Tian
parent b3799ff9c7
commit df42397cea
23 changed files with 3 additions and 1078 deletions

19
Cargo.lock generated
View File

@ -659,7 +659,6 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"component", "component",
"jinux-frame", "jinux-frame",
"jinux-pci",
"jinux-util", "jinux-util",
"jinux-virtio", "jinux-virtio",
"lazy_static", "lazy_static",
@ -716,7 +715,6 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"component", "component",
"jinux-frame", "jinux-frame",
"jinux-pci",
"jinux-rights", "jinux-rights",
"jinux-util", "jinux-util",
"jinux-virtio", "jinux-virtio",
@ -732,7 +730,6 @@ version = "0.1.0"
dependencies = [ dependencies = [
"component", "component",
"jinux-frame", "jinux-frame",
"jinux-pci",
"jinux-rights", "jinux-rights",
"jinux-util", "jinux-util",
"jinux-virtio", "jinux-virtio",
@ -742,21 +739,6 @@ dependencies = [
"spin 0.9.8", "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]] [[package]]
name = "jinux-rights" name = "jinux-rights"
version = "0.1.0" version = "0.1.0"
@ -847,7 +829,6 @@ dependencies = [
"component", "component",
"int-to-c-enum", "int-to-c-enum",
"jinux-frame", "jinux-frame",
"jinux-pci",
"jinux-rights", "jinux-rights",
"jinux-util", "jinux-util",
"log", "log",

View File

@ -22,7 +22,6 @@ jinux-framebuffer = { path = "services/comps/framebuffer" }
members = [ members = [
"build", "build",
"framework/jinux-frame", "framework/jinux-frame",
"services/comps/pci",
"services/comps/virtio", "services/comps/virtio",
"services/comps/input", "services/comps/input",
"services/comps/block", "services/comps/block",

View File

@ -1,7 +1,6 @@
# template # template
[components] [components]
std = { name = "jinux-std" } std = { name = "jinux-std" }
pci = { name = "jinux-pci" }
virtio = { name = "jinux-virtio" } virtio = { name = "jinux-virtio" }
input = { name = "jinux-input" } input = { name = "jinux-input" }
block = { name = "jinux-block" } block = { name = "jinux-block" }

View File

@ -3,5 +3,4 @@
pub mod cmos; pub mod cmos;
pub mod io_port; pub mod io_port;
pub mod pci;
pub mod serial; pub mod serial;

View File

@ -5,6 +5,7 @@ pub mod iommu;
pub(crate) mod irq; pub(crate) mod irq;
mod kernel; mod kernel;
pub(crate) mod mm; pub(crate) mod mm;
pub(crate) mod pci;
pub(crate) mod timer; pub(crate) mod timer;
use alloc::fmt; use alloc::fmt;

View File

@ -1,7 +1,6 @@
//! PCI bus io port //! PCI bus io port
use super::io_port::IoPort; use super::device::io_port::{IoPort, ReadWriteAccess, WriteOnlyAccess};
use super::io_port::{ReadWriteAccess, WriteOnlyAccess};
pub static PCI_ADDRESS_PORT: IoPort<u32, WriteOnlyAccess> = unsafe { IoPort::new(0x0CF8) }; pub static PCI_ADDRESS_PORT: IoPort<u32, WriteOnlyAccess> = unsafe { IoPort::new(0x0CF8) };
pub static PCI_DATA_PORT: IoPort<u32, ReadWriteAccess> = unsafe { IoPort::new(0x0CFC) }; pub static PCI_DATA_PORT: IoPort<u32, ReadWriteAccess> = unsafe { IoPort::new(0x0CFC) };

View File

@ -1,6 +1,6 @@
use core::iter; 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; use super::cfg_space::PciDeviceCommonCfgOffset;

View File

@ -9,7 +9,6 @@ edition = "2021"
bitflags = "1.3" bitflags = "1.3"
spin = "0.9.4" spin = "0.9.4"
jinux-frame = { path = "../../../framework/jinux-frame" } jinux-frame = { path = "../../../framework/jinux-frame" }
jinux-pci = { path = "../pci" }
jinux-virtio = { path = "../virtio" } jinux-virtio = { path = "../virtio" }
jinux-util = { path = "../../libs/jinux-util" } jinux-util = { path = "../../libs/jinux-util" }
component = { path = "../../libs/comp-sys/component" } component = { path = "../../libs/comp-sys/component" }

View File

@ -9,7 +9,6 @@ edition = "2021"
bitflags = "1.3" bitflags = "1.3"
spin = "0.9.4" spin = "0.9.4"
jinux-frame = { path = "../../../framework/jinux-frame" } jinux-frame = { path = "../../../framework/jinux-frame" }
jinux-pci = { path = "../pci" }
jinux-virtio = { path = "../virtio" } jinux-virtio = { path = "../virtio" }
jinux-util = { path = "../../libs/jinux-util" } jinux-util = { path = "../../libs/jinux-util" }
jinux-rights = { path = "../../libs/jinux-rights" } jinux-rights = { path = "../../libs/jinux-rights" }

View File

@ -10,7 +10,6 @@ component = { path = "../../libs/comp-sys/component" }
jinux-frame = { path = "../../../framework/jinux-frame" } jinux-frame = { path = "../../../framework/jinux-frame" }
jinux-virtio = { path = "../virtio" } jinux-virtio = { path = "../virtio" }
jinux-util = { path = "../../libs/jinux-util" } jinux-util = { path = "../../libs/jinux-util" }
jinux-pci = { path = "../pci" }
jinux-rights = { path = "../../libs/jinux-rights" } jinux-rights = { path = "../../libs/jinux-rights" }
spin = "0.9.4" spin = "0.9.4"
ringbuf = { version = "0.3.2", default-features = false, features = ["alloc"] } ringbuf = { version = "0.3.2", default-features = false, features = ["alloc"] }

View File

@ -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]

View File

@ -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,
}
}
}

View File

@ -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
}
}

View File

@ -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,
}
}
}

View File

@ -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),
}
}
}

View File

@ -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,
}
}
}

View File

@ -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,
}
}
}

View File

@ -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
)
}
}
}
}

View File

@ -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,
}
}
}

View File

@ -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()
}
}

View File

@ -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
}
}

View File

@ -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,
})
}

View File

@ -11,7 +11,6 @@ spin = "0.9.4"
bytes = { version = "1.4.0", default-features = false } bytes = { version = "1.4.0", default-features = false }
align_ext = { path = "../../../framework/libs/align_ext" } align_ext = { path = "../../../framework/libs/align_ext" }
jinux-frame = { path = "../../../framework/jinux-frame" } jinux-frame = { path = "../../../framework/jinux-frame" }
jinux-pci = { path = "../pci" }
jinux-util = { path = "../../libs/jinux-util" } jinux-util = { path = "../../libs/jinux-util" }
jinux-rights = { path = "../../libs/jinux-rights" } jinux-rights = { path = "../../libs/jinux-rights" }
typeflags-util = { path = "../../libs/typeflags-util" } typeflags-util = { path = "../../libs/typeflags-util" }