diff --git a/services/comps/pci/src/capability/exp.rs b/services/comps/pci/src/capability/exp.rs index 5f2926e4f..6018054c4 100644 --- a/services/comps/pci/src/capability/exp.rs +++ b/services/comps/pci/src/capability/exp.rs @@ -1,4 +1,5 @@ -use crate::util::{CSpaceAccessMethod, Location}; +use crate::util::CSpaceAccessMethod; +use jinux_frame::bus::pci::PciDeviceLocation; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct CapabilityEXPData { @@ -9,7 +10,7 @@ pub struct CapabilityEXPData { } impl CapabilityEXPData { - pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self { + pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self { let am = CSpaceAccessMethod::IO; let cap = am.read16(loc, cap_ptr + 0x2); Self { diff --git a/services/comps/pci/src/capability/mod.rs b/services/comps/pci/src/capability/mod.rs index 5e231f4e9..1d8be9190 100644 --- a/services/comps/pci/src/capability/mod.rs +++ b/services/comps/pci/src/capability/mod.rs @@ -1,6 +1,7 @@ //! This mod is used in frame to do device initialization -use crate::util::*; +use crate::util::CSpaceAccessMethod; use alloc::vec::Vec; +use jinux_frame::bus::pci::PciDeviceLocation; use self::{ exp::CapabilityEXPData, msi::CapabilityMSIData, msix::CapabilityMSIXData, pm::CapabilityPMData, @@ -70,7 +71,7 @@ pub struct Capability { impl Capability { /// get the capabilities of one device - pub fn device_capabilities(loc: Location) -> Vec { + pub fn device_capabilities(loc: PciDeviceLocation) -> Vec { let mut capabilities = Vec::new(); let am = CSpaceAccessMethod::IO; let mut cap_ptr = am.read8(loc, PCI_CAP_PTR) as u16; diff --git a/services/comps/pci/src/capability/msi.rs b/services/comps/pci/src/capability/msi.rs index c0c631798..68918be3b 100644 --- a/services/comps/pci/src/capability/msi.rs +++ b/services/comps/pci/src/capability/msi.rs @@ -1,5 +1,6 @@ -use crate::util::{CSpaceAccessMethod, Location}; +use crate::util::CSpaceAccessMethod; use bitflags::bitflags; +use jinux_frame::bus::pci::PciDeviceLocation; bitflags! { pub struct CapabilityMSIMessageControl: u16 { const ADDR64_CAPABLE = 1 << 7; @@ -25,7 +26,7 @@ pub struct CapabilityMSIData { } impl CapabilityMSIData { - pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self { + 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)); diff --git a/services/comps/pci/src/capability/msix.rs b/services/comps/pci/src/capability/msix.rs index feca8ba7c..b88733424 100644 --- a/services/comps/pci/src/capability/msix.rs +++ b/services/comps/pci/src/capability/msix.rs @@ -1,4 +1,5 @@ -use crate::util::*; +use crate::util::CSpaceAccessMethod; +use jinux_frame::bus::pci::PciDeviceLocation; #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[repr(C)] @@ -9,7 +10,7 @@ pub struct CapabilityMSIXData { } impl CapabilityMSIXData { - pub fn new(loc: Location, cap_ptr: u16) -> Self { + pub fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self { let am = CSpaceAccessMethod::IO; Self { message_control: am.read16(loc, cap_ptr + 2), diff --git a/services/comps/pci/src/capability/pm.rs b/services/comps/pci/src/capability/pm.rs index 895430b71..0c68b750b 100644 --- a/services/comps/pci/src/capability/pm.rs +++ b/services/comps/pci/src/capability/pm.rs @@ -1,4 +1,5 @@ -use crate::util::{CSpaceAccessMethod, Location}; +use crate::util::CSpaceAccessMethod; +use jinux_frame::bus::pci::PciDeviceLocation; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct CapabilityPMData { @@ -12,7 +13,7 @@ pub struct CapabilityPMData { } impl CapabilityPMData { - pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self { + pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self { let am = CSpaceAccessMethod::IO; let cap = am.read32(loc, cap_ptr + 0x4); Self { diff --git a/services/comps/pci/src/capability/sata.rs b/services/comps/pci/src/capability/sata.rs index bc296afbc..c4a62ccb2 100644 --- a/services/comps/pci/src/capability/sata.rs +++ b/services/comps/pci/src/capability/sata.rs @@ -1,4 +1,5 @@ -use crate::util::{CSpaceAccessMethod, Location}; +use crate::util::CSpaceAccessMethod; +use jinux_frame::bus::pci::PciDeviceLocation; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct CapabilitySATAData { @@ -9,7 +10,7 @@ pub struct CapabilitySATAData { } impl CapabilitySATAData { - pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self { + 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); diff --git a/services/comps/pci/src/capability/vendor/mod.rs b/services/comps/pci/src/capability/vendor/mod.rs index c64e13741..53930ddfd 100644 --- a/services/comps/pci/src/capability/vendor/mod.rs +++ b/services/comps/pci/src/capability/vendor/mod.rs @@ -2,7 +2,8 @@ pub mod virtio; use virtio::CapabilityVirtioData; -use crate::util::{CSpaceAccessMethod, Location}; +use crate::util::CSpaceAccessMethod; +use jinux_frame::bus::pci::PciDeviceLocation; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum CapabilityVNDRData { @@ -11,7 +12,7 @@ pub enum CapabilityVNDRData { } impl CapabilityVNDRData { - pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self { + pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self { let am = CSpaceAccessMethod::IO; let vid = am.read16(loc, 0); match vid { diff --git a/services/comps/pci/src/capability/vendor/virtio.rs b/services/comps/pci/src/capability/vendor/virtio.rs index 6bf82f7f7..b85e3ca38 100644 --- a/services/comps/pci/src/capability/vendor/virtio.rs +++ b/services/comps/pci/src/capability/vendor/virtio.rs @@ -1,4 +1,5 @@ -use crate::util::*; +use crate::util::CSpaceAccessMethod; +use jinux_frame::bus::pci::PciDeviceLocation; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct CapabilityVirtioData { @@ -10,7 +11,7 @@ pub struct CapabilityVirtioData { } impl CapabilityVirtioData { - pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self { + 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 { diff --git a/services/comps/pci/src/lib.rs b/services/comps/pci/src/lib.rs index a97eef42b..44cd4bb93 100644 --- a/services/comps/pci/src/lib.rs +++ b/services/comps/pci/src/lib.rs @@ -11,10 +11,11 @@ use component::init_component; use component::ComponentInitError; use alloc::{sync::Arc, vec::Vec}; +use jinux_frame::bus::pci::PciDeviceLocation; use spin::{mutex::Mutex, Once}; use util::CSpaceAccessMethod; -pub use crate::util::PCIDevice; +pub use crate::util::PciDevice; pub const PCI_COMMAND: u16 = 0x04; pub const PCI_BAR: u16 = 0x10; @@ -37,28 +38,31 @@ fn pci_component_init() -> Result<(), ComponentInitError> { Ok(()) } pub struct PCIComponent { - pci_device: Mutex>>, + pci_device: Mutex>>, } impl PCIComponent { pub fn init() -> Result { let mut devices = Vec::new(); - for dev in util::scan_bus(CSpaceAccessMethod::IO) { + 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: {}:{:?}", - dev.loc.bus, - dev.loc.device, - dev.loc.function, - dev.id.vendor_id, - dev.id.device_id, - dev.id.class, - dev.id.subclass, - dev.command, - dev.status, - dev.pic_interrupt_line, - dev.interrupt_pin + 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(dev)); + devices.push(Arc::new(device)); } Ok(Self { pci_device: Mutex::new(devices), @@ -75,7 +79,7 @@ impl PCIComponent { } impl PCIComponent { - pub fn get_pci_devices(self: &Self, index: usize) -> Option> { + pub fn get_pci_devices(self: &Self, index: usize) -> Option> { self.pci_device.lock().get(index).cloned() } diff --git a/services/comps/pci/src/msix.rs b/services/comps/pci/src/msix.rs index ecc0bb03e..3014d40e3 100644 --- a/services/comps/pci/src/msix.rs +++ b/services/comps/pci/src/msix.rs @@ -2,11 +2,11 @@ use alloc::vec::Vec; use log::debug; use pod::Pod; -use crate::util::{CSpaceAccessMethod, Location, BAR}; +use crate::util::{CSpaceAccessMethod, BAR}; use super::capability::msix::CapabilityMSIXData; -use jinux_frame::{offset_of, trap::IrqAllocateHandle}; +use jinux_frame::{bus::pci::PciDeviceLocation, offset_of, trap::IrqAllocateHandle}; use jinux_util::frame_ptr::InFramePtr; #[derive(Debug, Default)] @@ -37,7 +37,7 @@ impl MSIX { pub fn new( cap: &CapabilityMSIXData, bars: [Option; 6], - loc: Location, + loc: PciDeviceLocation, cap_ptr: u16, ) -> Self { let table_info = cap.table_info; diff --git a/services/comps/pci/src/util.rs b/services/comps/pci/src/util.rs index 9192d97d8..4fdef4e23 100644 --- a/services/comps/pci/src/util.rs +++ b/services/comps/pci/src/util.rs @@ -2,6 +2,7 @@ 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, @@ -46,19 +47,19 @@ pub enum CSpaceAccessMethod { // All IO-bus ops are 32-bit, we mask and shift to get the values we want. impl CSpaceAccessMethod { - pub fn read8(self, loc: Location, offset: u16) -> u8 { + 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: Location, offset: u16) -> u16 { + 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: Location, offset: u16) -> u32 { + pub fn read32(self, loc: PciDeviceLocation, offset: u16) -> u32 { debug_assert!( (offset & 0b11) == 0, "misaligned PCI configuration dword u32 read" @@ -66,7 +67,7 @@ impl CSpaceAccessMethod { match self { CSpaceAccessMethod::IO => { jinux_frame::arch::x86::device::pci::PCI_ADDRESS_PORT - .write(loc.encode() | ((offset as u32) & 0b11111100)); + .write(loc.encode_as_x86_address_value() | ((offset as u32) & 0b11111100)); jinux_frame::arch::x86::device::pci::PCI_DATA_PORT .read() .to_le() @@ -77,7 +78,7 @@ impl CSpaceAccessMethod { } } - pub fn write8(self, loc: Location, offset: u16, val: u8) { + 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; @@ -89,7 +90,7 @@ impl CSpaceAccessMethod { } /// Converts val to little endian before writing. - pub fn write16(self, loc: Location, offset: u16, val: u16) { + 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; @@ -102,7 +103,7 @@ impl CSpaceAccessMethod { /// 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: Location, offset: u16, val: u32) { + pub fn write32(self, loc: PciDeviceLocation, offset: u16, val: u32) { debug_assert!( (offset & 0b11) == 0, "misaligned PCI configuration dword u32 read" @@ -110,7 +111,7 @@ impl CSpaceAccessMethod { match self { CSpaceAccessMethod::IO => { jinux_frame::arch::x86::device::pci::PCI_ADDRESS_PORT - .write(loc.encode() | (offset as u32 & 0b11111100)); + .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. @@ -120,24 +121,6 @@ impl CSpaceAccessMethod { } } -/// Physical location of a device on the bus -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Location { - pub bus: u8, - pub device: u8, - pub function: u8, -} - -impl Location { - #[inline(always)] - fn encode(self) -> u32 { - (1 << 31) - | ((self.bus as u32) << 16) - | (((self.device as u32) & 0b11111) << 11) - | (((self.function as u32) & 0b111) << 8) - } -} - #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct Identifier { pub vendor_id: u16, @@ -215,8 +198,8 @@ bitflags! { /// /// Although accessing configuration space may be expensive, it is not cached. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct PCIDevice { - pub loc: Location, +pub struct PciDevice { + pub loc: PciDeviceLocation, pub id: Identifier, pub command: Command, pub status: Status, @@ -232,7 +215,7 @@ pub struct PCIDevice { pub capabilities: Vec, } -impl PCIDevice { +impl PciDevice { /// set the status bits pub fn set_status_bits(&self, status: Status) { let am = CSpaceAccessMethod::IO; @@ -328,7 +311,11 @@ pub enum BAR { } impl BAR { - pub fn decode(loc: Location, am: CSpaceAccessMethod, idx: u16) -> (Option, usize) { + pub fn decode( + loc: PciDeviceLocation, + am: CSpaceAccessMethod, + idx: u16, + ) -> (Option, 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)); @@ -370,66 +357,7 @@ impl BAR { } } -pub(crate) struct BusScan { - loc: Location, - am: CSpaceAccessMethod, -} - -impl BusScan { - fn done(&self) -> bool { - if self.loc.bus == 255 && self.loc.device == 31 && self.loc.function == 7 { - true - } else { - false - } - } - - fn increment(&mut self) { - // TODO: Decide whether this is actually nicer than taking a u16 and incrementing until it - // wraps. - if self.loc.function < 7 { - self.loc.function += 1; - return; - } else { - self.loc.function = 0; - if self.loc.device < 31 { - self.loc.device += 1; - return; - } else { - self.loc.device = 0; - if self.loc.bus == 255 { - self.loc.device = 31; - self.loc.device = 7; - } else { - self.loc.bus += 1; - return; - } - } - } - } -} - -impl ::core::iter::Iterator for BusScan { - type Item = PCIDevice; - #[inline] - fn next(&mut self) -> Option { - // FIXME: very naive atm, could be smarter and waste much less time by only scanning used - // busses. - let mut ret = None; - loop { - if self.done() { - return ret; - } - ret = probe_function(self.loc, self.am); - self.increment(); - if ret.is_some() { - return ret; - } - } - } -} - -fn probe_function(loc: Location, am: CSpaceAccessMethod) -> Option { +pub(crate) fn find_device(loc: PciDeviceLocation, am: CSpaceAccessMethod) -> Option { // FIXME: it'd be more efficient to use read32 and decode separately. let vid = am.read16(loc, 0); if vid == 0xFFFF { @@ -551,7 +479,7 @@ fn probe_function(loc: Location, am: CSpaceAccessMethod) -> Option { i = next; } - Some(PCIDevice { + Some(PciDevice { loc: loc, id: id, command: command, @@ -568,14 +496,3 @@ fn probe_function(loc: Location, am: CSpaceAccessMethod) -> Option { capabilities: capabilities, }) } - -pub(crate) fn scan_bus(am: CSpaceAccessMethod) -> BusScan { - BusScan { - loc: Location { - bus: 0, - device: 0, - function: 0, - }, - am: am, - } -} diff --git a/services/comps/virtio/src/lib.rs b/services/comps/virtio/src/lib.rs index 4681819f2..17d58572f 100644 --- a/services/comps/virtio/src/lib.rs +++ b/services/comps/virtio/src/lib.rs @@ -13,7 +13,7 @@ use bitflags::bitflags; use component::ComponentInitError; use device::VirtioDevice; use jinux_frame::{offset_of, trap::TrapFrame}; -use jinux_pci::util::{PCIDevice, BAR}; +use jinux_pci::{util::BAR, PciDevice}; use jinux_util::frame_ptr::InFramePtr; use log::{debug, info}; use pod::Pod; @@ -226,7 +226,7 @@ pub struct PCIVirtioDevice { impl PCIVirtioDevice { /// create a new PCI Virtio Device, note that this function will stop with device status features ok - pub fn new(dev: Arc) -> Self { + pub fn new(dev: Arc) -> Self { assert_eq!(dev.id.vendor_id, 0x1af4); let device_type = match dev.id.device_id { 0x1000 | 0x1041 => VirtioDeviceType::Network,