diff --git a/kernel/comps/virtio/src/transport/mmio/device.rs b/kernel/comps/virtio/src/transport/mmio/device.rs index 3a5828d95..c0847ad76 100644 --- a/kernel/comps/virtio/src/transport/mmio/device.rs +++ b/kernel/comps/virtio/src/transport/mmio/device.rs @@ -9,7 +9,7 @@ use log::warn; use ostd::{ bus::mmio::{ bus::MmioDevice, - device::{MmioCommonDevice, VirtioMmioVersion}, + common_device::{MmioCommonDevice, VirtioMmioVersion}, }, io_mem::IoMem, mm::{DmaCoherent, PAGE_SIZE}, @@ -34,7 +34,7 @@ pub struct VirtioMmioDevice { pub struct VirtioMmioTransport { layout: SafePtr, device: Arc, - common_device: ostd::bus::mmio::device::MmioCommonDevice, + common_device: ostd::bus::mmio::common_device::MmioCommonDevice, multiplex: Arc>, } diff --git a/kernel/comps/virtio/src/transport/mmio/driver.rs b/kernel/comps/virtio/src/transport/mmio/driver.rs index 5bc793a22..39f13625a 100644 --- a/kernel/comps/virtio/src/transport/mmio/driver.rs +++ b/kernel/comps/virtio/src/transport/mmio/driver.rs @@ -6,7 +6,7 @@ use ostd::{ bus::{ mmio::{ bus::{MmioDevice, MmioDriver}, - device::MmioCommonDevice, + common_device::MmioCommonDevice, }, BusProbeError, }, diff --git a/ostd/src/arch/x86/device/mod.rs b/ostd/src/arch/x86/device/mod.rs index 5b900f240..d588d790a 100644 --- a/ostd/src/arch/x86/device/mod.rs +++ b/ostd/src/arch/x86/device/mod.rs @@ -3,9 +3,6 @@ //! Device-related APIs. //! This module mainly contains the APIs that should exposed to the device driver like PCI, RTC -// FIXME: remove this lint when the documentation of this module is extensively added. -#![allow(missing_docs)] - pub mod cmos; pub mod io_port; pub mod serial; diff --git a/ostd/src/bus/mmio/bus.rs b/ostd/src/bus/mmio/bus.rs index e57535c54..d7dbd9ae8 100644 --- a/ostd/src/bus/mmio/bus.rs +++ b/ostd/src/bus/mmio/bus.rs @@ -1,15 +1,19 @@ // SPDX-License-Identifier: MPL-2.0 +//! MMIO bus. + #![allow(unused_variables)] use alloc::{collections::VecDeque, fmt::Debug, sync::Arc, vec::Vec}; use log::{debug, error}; -use super::device::MmioCommonDevice; +use super::common_device::MmioCommonDevice; use crate::bus::BusProbeError; +/// MMIO device trait pub trait MmioDevice: Sync + Send + Debug { + /// Device ID fn device_id(&self) -> u32; } @@ -37,6 +41,7 @@ pub struct MmioBus { } impl MmioBus { + /// Registers a MMIO driver to the MMIO bus. pub fn register_driver(&mut self, driver: Arc) { debug!("Register driver:{:#x?}", driver); let length = self.common_devices.len(); diff --git a/ostd/src/bus/mmio/common_device.rs b/ostd/src/bus/mmio/common_device.rs new file mode 100644 index 000000000..d83a2abb4 --- /dev/null +++ b/ostd/src/bus/mmio/common_device.rs @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MPL-2.0 + +//! MMIO device common definitions or functions. + +use int_to_c_enum::TryFromInt; +use log::info; + +use super::VIRTIO_MMIO_MAGIC; +use crate::{ + io_mem::IoMem, + mm::{paddr_to_vaddr, Paddr, VmIo}, + trap::IrqLine, +}; + +/// MMIO Common device. +#[derive(Debug)] +pub struct MmioCommonDevice { + io_mem: IoMem, + irq: IrqLine, +} + +impl MmioCommonDevice { + pub(super) fn new(paddr: Paddr, handle: IrqLine) -> Self { + // TODO: Implement universal access to MMIO devices since we are temporarily + // using specific virtio device as implementation of CommonDevice. + + // Read magic value + // SAFETY: It only read the value and judge if the magic value fit 0x74726976 + unsafe { + debug_assert_eq!(*(paddr_to_vaddr(paddr) as *const u32), VIRTIO_MMIO_MAGIC); + } + // SAFETY: This range is virtio-mmio device space. + let io_mem = unsafe { IoMem::new(paddr..paddr + 0x200) }; + let res = Self { + io_mem, + irq: handle, + }; + info!( + "[Virtio]: Found Virtio mmio device, device id:{:?}, irq number:{:?}", + res.device_id(), + res.irq.num() + ); + res + } + + /// Base address + pub fn address(&self) -> Paddr { + self.io_mem.paddr() + } + + /// Grants access to the MMIO + pub fn io_mem(&self) -> &IoMem { + &self.io_mem + } + + /// Device ID + pub fn device_id(&self) -> u32 { + self.io_mem.read_val::(8).unwrap() + } + + /// Version of the MMIO device. + pub fn version(&self) -> VirtioMmioVersion { + VirtioMmioVersion::try_from(self.io_mem.read_val::(4).unwrap()).unwrap() + } + + /// Interrupt line + pub fn irq(&self) -> &IrqLine { + &self.irq + } + + /// Mutable Interrupt line + pub fn irq_mut(&mut self) -> &mut IrqLine { + &mut self.irq + } +} + +/// Virtio MMIO version +#[derive(Debug, Clone, Copy, TryFromInt, PartialEq, Eq, PartialOrd, Ord)] +#[repr(u32)] +pub enum VirtioMmioVersion { + /// Legacy + Legacy = 1, + /// Modern + Modern = 2, +} diff --git a/ostd/src/bus/mmio/device.rs b/ostd/src/bus/mmio/device.rs index 136ba35e6..a8992ff8a 100644 --- a/ostd/src/bus/mmio/device.rs +++ b/ostd/src/bus/mmio/device.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! MMIO device common definitions or functions. + use int_to_c_enum::TryFromInt; use log::info; @@ -40,34 +42,45 @@ impl MmioCommonDevice { res } + /// Base address pub fn address(&self) -> Paddr { self.io_mem.paddr() } + /// Grants access to the MMIO pub fn io_mem(&self) -> &IoMem { &self.io_mem } + /// Device ID pub fn device_id(&self) -> u32 { self.io_mem.read_val::(8).unwrap() } + /// Version of the MMIO device. + /// + /// FIXME: This function can only used in Virtio-mmio devices. pub fn version(&self) -> VirtioMmioVersion { VirtioMmioVersion::try_from(self.io_mem.read_val::(4).unwrap()).unwrap() } + /// Interrupt line pub fn irq(&self) -> &IrqLine { &self.irq } + /// Mutable Interrupt line pub fn irq_mut(&mut self) -> &mut IrqLine { &mut self.irq } } +/// Virtio MMIO version #[derive(Debug, Clone, Copy, TryFromInt, PartialEq, Eq, PartialOrd, Ord)] #[repr(u32)] pub enum VirtioMmioVersion { + /// Legacy Legacy = 1, + /// Modern Modern = 2, } diff --git a/ostd/src/bus/mmio/mod.rs b/ostd/src/bus/mmio/mod.rs index 8da0b20ce..67072ec32 100644 --- a/ostd/src/bus/mmio/mod.rs +++ b/ostd/src/bus/mmio/mod.rs @@ -5,7 +5,7 @@ //! Virtio over MMIO pub mod bus; -pub mod device; +pub mod common_device; use alloc::vec::Vec; use core::ops::Range; @@ -18,16 +18,17 @@ use self::bus::MmioBus; #[cfg(feature = "intel_tdx")] use crate::arch::tdx_guest; use crate::{ - arch::kernel::IO_APIC, bus::mmio::device::MmioCommonDevice, mm::paddr_to_vaddr, sync::SpinLock, - trap::IrqLine, + arch::kernel::IO_APIC, bus::mmio::common_device::MmioCommonDevice, mm::paddr_to_vaddr, + sync::SpinLock, trap::IrqLine, }; const VIRTIO_MMIO_MAGIC: u32 = 0x74726976; +/// MMIO bus instance pub static MMIO_BUS: SpinLock = SpinLock::new(MmioBus::new()); static IRQS: SpinLock> = SpinLock::new(Vec::new()); -pub fn init() { +pub(crate) fn init() { #[cfg(feature = "intel_tdx")] // SAFETY: // This is safe because we are ensuring that the address range 0xFEB0_0000 to 0xFEB0_4000 is valid before this operation. diff --git a/ostd/src/bus/mod.rs b/ostd/src/bus/mod.rs index ebc8dfc43..f22a58363 100644 --- a/ostd/src/bus/mod.rs +++ b/ostd/src/bus/mod.rs @@ -2,9 +2,6 @@ //! Bus operations -// FIXME: remove this lint when the docs of the whole bus module are added. -#![allow(missing_docs)] - pub mod mmio; pub mod pci; @@ -18,7 +15,7 @@ pub enum BusProbeError { } /// Initializes the bus -pub fn init() { +pub(crate) fn init() { pci::init(); mmio::init(); } diff --git a/ostd/src/bus/pci/bus.rs b/ostd/src/bus/pci/bus.rs index c764d126c..d0a28a786 100644 --- a/ostd/src/bus/pci/bus.rs +++ b/ostd/src/bus/pci/bus.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! PCI bus + #![allow(unused_variables)] use alloc::{collections::VecDeque, sync::Arc, vec::Vec}; @@ -10,7 +12,9 @@ use log::{debug, error}; use super::{device_info::PciDeviceId, PciCommonDevice}; use crate::bus::BusProbeError; +/// PciDevice trait. pub trait PciDevice: Sync + Send + Debug { + /// Gets device id. fn device_id(&self) -> PciDeviceId; } @@ -42,6 +46,7 @@ pub struct PciBus { } impl PciBus { + /// Registers a PCI driver to the PCI bus. pub fn register_driver(&mut self, driver: Arc) { debug!("Register driver:{:#x?}", driver); let length = self.common_devices.len(); diff --git a/ostd/src/bus/pci/capability/mod.rs b/ostd/src/bus/pci/capability/mod.rs index e0535e6e3..875ea9e3c 100644 --- a/ostd/src/bus/pci/capability/mod.rs +++ b/ostd/src/bus/pci/capability/mod.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! PCI device capabilities. + #![allow(dead_code)] use alloc::vec::Vec; @@ -14,6 +16,7 @@ use super::{ pub mod msix; pub mod vendor; +/// PCI Capability #[derive(Debug)] pub struct Capability { id: u8, @@ -26,6 +29,7 @@ pub struct Capability { cap_data: CapabilityData, } +/// PCI Capability data. #[derive(Debug, Clone)] pub enum CapabilityData { /// Id:0x01, Power Management @@ -76,11 +80,12 @@ impl Capability { /// 0xFC, the top of the capability position. const CAPABILITY_TOP: u16 = 0xFC; + /// Gets the capability data pub fn capability_data(&self) -> &CapabilityData { &self.cap_data } - /// get the capabilities of one device + /// Gets the capabilities of one device pub(super) fn device_capabilities(dev: &mut PciCommonDevice) -> Vec { if !dev.status().contains(Status::CAPABILITIES_LIST) { return Vec::new(); diff --git a/ostd/src/bus/pci/capability/msix.rs b/ostd/src/bus/pci/capability/msix.rs index fe0491832..6fe68411d 100644 --- a/ostd/src/bus/pci/capability/msix.rs +++ b/ostd/src/bus/pci/capability/msix.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! MSI-X capability support. + #![allow(dead_code)] #![allow(unused_variables)] @@ -150,11 +152,13 @@ impl CapabilityMsixData { } } + /// MSI-X Table size pub fn table_size(&self) -> u16 { // bit 10:0 table size (self.loc.read16(self.ptr + 2) & 0b11_1111_1111) + 1 } + /// Enables an interrupt line, it will replace the old handle with the new handle. pub fn set_interrupt_vector(&mut self, handle: IrqLine, index: u16) { if index >= self.table_size { return; @@ -174,6 +178,7 @@ impl CapabilityMsixData { .unwrap(); } + /// Gets mutable IrqLine. User can register callbacks by using this function. pub fn irq_mut(&mut self, index: usize) -> Option<&mut IrqLine> { self.irqs[index].as_mut() } diff --git a/ostd/src/bus/pci/capability/vendor.rs b/ostd/src/bus/pci/capability/vendor.rs index 0013168bd..b2bb4cc12 100644 --- a/ostd/src/bus/pci/capability/vendor.rs +++ b/ostd/src/bus/pci/capability/vendor.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! Vendor-specific capability support. + use crate::{ bus::pci::{common_device::PciCommonDevice, device_info::PciDeviceLocation}, Error, Result, @@ -23,41 +25,45 @@ impl CapabilityVndrData { } } + /// The length of this capability + #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> u16 { self.length } - pub fn is_empty(&self) -> bool { - self.length == 0 - } - + /// Reads u8 from the capability. pub fn read8(&self, offset: u16) -> Result { self.check_range(offset)?; Ok(self.location.read8(self.cap_ptr + offset)) } + /// Writes u8 to the capability. pub fn write8(&self, offset: u16, value: u8) -> Result<()> { self.check_range(offset)?; self.location.write8(self.cap_ptr + offset, value); Ok(()) } + /// Reads u16 from the capability. pub fn read16(&self, offset: u16) -> Result { self.check_range(offset)?; Ok(self.location.read16(self.cap_ptr + offset)) } + /// Writes u16 to the capability. pub fn write16(&self, offset: u16, value: u16) -> Result<()> { self.check_range(offset)?; self.location.write16(self.cap_ptr + offset, value); Ok(()) } + /// Reads u32 from the capability. pub fn read32(&self, offset: u16) -> Result { self.check_range(offset)?; Ok(self.location.read32(self.cap_ptr + offset)) } + /// Writes u32 to the capability. pub fn write32(&self, offset: u16, value: u32) -> Result<()> { self.check_range(offset)?; self.location.write32(self.cap_ptr + offset, value); diff --git a/ostd/src/bus/pci/cfg_space.rs b/ostd/src/bus/pci/cfg_space.rs index 5718b853a..09130e4ee 100644 --- a/ostd/src/bus/pci/cfg_space.rs +++ b/ostd/src/bus/pci/cfg_space.rs @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MPL-2.0 +//! The PCI configuration space. +//! +//! Reference: + use alloc::sync::Arc; use core::mem::size_of; @@ -12,48 +16,87 @@ use crate::{ Error, Result, }; +/// Offset in PCI device's common configuration space(Not the PCI bridge). #[repr(u16)] pub enum PciDeviceCommonCfgOffset { + /// Vendor ID VendorId = 0x00, + /// Device ID DeviceId = 0x02, + /// PCI Command Command = 0x04, + /// PCI Status Status = 0x06, + /// Revision ID RevisionId = 0x08, + /// Class code ClassCode = 0x09, + /// Cache Line Size CacheLineSize = 0x0C, + /// Latency Timer LatencyTimer = 0x0D, + /// Header Type: Identifies the layout of the header. HeaderType = 0x0E, + /// BIST: Represents the status and allows control of a devices BIST(built-in self test). Bist = 0x0F, + /// Base Address Register #0 Bar0 = 0x10, + /// Base Address Register #1 Bar1 = 0x14, + /// Base Address Register #2 Bar2 = 0x18, + /// Base Address Register #3 Bar3 = 0x1C, + /// Base Address Register #4 Bar4 = 0x20, + /// Base Address Register #5 Bar5 = 0x24, + /// Cardbus CIS Pointer CardbusCisPtr = 0x28, + /// Subsystem Vendor ID SubsystemVendorId = 0x2C, + /// Subsystem ID SubsystemId = 0x2E, + /// Expansion ROM base address XromBar = 0x30, + /// Capabilities pointer CapabilitiesPointer = 0x34, + /// Interrupt Line InterruptLine = 0x3C, + /// INterrupt PIN InterruptPin = 0x3D, + /// Min Grant MinGrant = 0x3E, + /// Max latency MaxLatency = 0x3F, } bitflags! { /// PCI device common config space command register. pub struct Command: u16 { + /// Sets to 1 if the device can respond to I/O Space accesses. const IO_SPACE = 1 << 0; + /// Sets to 1 if the device can respond to Memory SPace accesses. const MEMORY_SPACE = 1 << 1; + /// Sets to 1 if the device can behave as a bus master. const BUS_MASTER = 1 << 2; + /// Sets to 1 if the device can monitor Special Cycle operations. const SPECIAL_CYCLES = 1 << 3; + /// Memory Write and Invalidate Enable. Set to 1 if the device can + /// generate the Memory Write and Invalidate command. const MWI_ENABLE = 1 << 4; + /// Sets to 1 if the device does not respond to palette register writes + /// and will snoop the data. const VGA_PALETTE_SNOOP = 1 << 5; + /// Sets to 1 if the device will takes its normal action when a parity + /// error is detected. const PARITY_ERROR_RESPONSE = 1 << 6; - const STEPPING_CONTROL = 1 << 7; + /// Sets to 1 if the SERR# driver is enabled. const SERR_ENABLE = 1 << 8; + /// Sets to 1 if the device is allowed to generate fast back-to-back + /// transactions const FAST_BACK_TO_BACK_ENABLE = 1 << 9; + /// Sets to 1 if the assertion of the devices INTx# signal is disabled. const INTERRUPT_DISABLE = 1 << 10; } } @@ -61,17 +104,45 @@ bitflags! { bitflags! { /// PCI device common config space status register. pub struct Status: u16 { + /// The status of the device's INTx# signal. const INTERRUPT_STATUS = 1 << 3; + /// Sets to 1 if the device support capabilities. const CAPABILITIES_LIST = 1 << 4; + /// Sets to 1 if the device is capable of running at 66 MHz. const MHZ66_CAPABLE = 1 << 5; + /// Sets to 1 if the device can accpet fast back-to-back transactions + /// that are not from the same agent. const FAST_BACK_TO_BACK_CAPABLE = 1 << 7; + /// This bit is only set when the following conditions are met: + /// 1. The bus agent asserted PERR# on a read or observed an assertion + /// of PERR# on a write + /// 2. The agent setting the bit acted as the bus master for the + /// operation in which the error occurred + /// 3. Bit 6 of the Command register (Parity Error Response bit) is set + /// to 1. const MASTER_DATA_PARITY_ERROR = 1 << 8; + /// The read-only bit that represent the slowest time that a device will + /// assert DEVSEL# for any bus command except Configuration Space read + /// and writes. + /// + /// If both `DEVSEL_MEDIUM_TIMING` and `DEVSEL_SLOW_TIMING` are not set, + /// then it represents fast timing const DEVSEL_MEDIUM_TIMING = 1 << 9; + /// Check `DEVSEL_MEDIUM_TIMING` const DEVSEL_SLOW_TIMING = 1 << 10; + /// Sets to 1 when a target device terminates a transaction with Target- + /// Abort. const SIGNALED_TARGET_ABORT = 1 << 11; + /// Sets to 1 by a master device when its transaction is terminated with + /// Target-Abort const RECEIVED_TARGET_ABORT = 1 << 12; + /// Sets to 1 by a master device when its transcation (except for Special + /// Cycle transactions) is terminated with Master-Abort. const RECEIVED_MASTER_ABORT = 1 << 13; + /// Sets to 1 when the device asserts SERR# const SIGNALED_SYSTEM_ERROR = 1 << 14; + /// Sets to 1 when the device detects a parity error, even if parity error + /// handling is disabled. const DETECTED_PARITY_ERROR = 1 << 15; } } @@ -79,7 +150,9 @@ bitflags! { /// BAR space in PCI common config space. #[derive(Debug, Clone)] pub enum Bar { + /// Memory BAR Memory(Arc), + /// I/O BAR Io(Arc), } @@ -103,12 +176,11 @@ impl Bar { } } +/// Memory BAR #[derive(Debug, Clone)] pub struct MemoryBar { base: u64, size: u32, - /// Whether this bar is prefetchable, allowing the CPU to get the data - /// in advance. prefetchable: bool, address_length: AddrLen, io_memory: IoMem, @@ -120,23 +192,28 @@ impl MemoryBar { self.address_length } + /// Whether this bar is prefetchable, allowing the CPU to get the data + /// in advance. pub fn prefetchable(&self) -> bool { self.prefetchable } + /// Base address pub fn base(&self) -> u64 { self.base } + /// Size of the memory pub fn size(&self) -> u32 { self.size } + /// Grants I/O memory access pub fn io_mem(&self) -> &IoMem { &self.io_memory } - /// Create a memory BAR structure. + /// Creates a memory BAR structure. fn new(location: &PciDeviceLocation, index: u8) -> Result { // Get the original value first, then write all 1 to the register to get the length let offset = index as u16 * 4 + PciDeviceCommonCfgOffset::Bar0 as u16; @@ -175,10 +252,13 @@ impl MemoryBar { /// Whether this BAR is 64bit address or 32bit address #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum AddrLen { + /// 32 bits Bits32, + /// 64 bits Bits64, } +/// I/O port BAR. #[derive(Debug, Clone, Copy)] pub struct IoBar { base: u32, @@ -186,14 +266,17 @@ pub struct IoBar { } impl IoBar { + /// Base port pub fn base(&self) -> u32 { self.base } + /// Size of the port pub fn size(&self) -> u32 { self.size } + /// Reads from port pub fn read(&self, offset: u32) -> Result { // Check alignment if (self.base + offset) % size_of::() as u32 != 0 { @@ -208,6 +291,7 @@ impl IoBar { unsafe { Ok(T::read_from_port((self.base + offset) as u16)) } } + /// Writes to port pub fn write(&self, offset: u32, value: T) -> Result<()> { // Check alignment if (self.base + offset) % size_of::() as u32 != 0 { diff --git a/ostd/src/bus/pci/common_device.rs b/ostd/src/bus/pci/common_device.rs index 7b394ba42..cd079b3df 100644 --- a/ostd/src/bus/pci/common_device.rs +++ b/ostd/src/bus/pci/common_device.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! PCI device common definitions or functions. + #![allow(dead_code)] #![allow(unused_variables)] @@ -21,22 +23,27 @@ pub struct PciCommonDevice { } impl PciCommonDevice { + /// PCI device ID pub fn device_id(&self) -> &PciDeviceId { &self.device_id } + /// PCI device location pub fn location(&self) -> &PciDeviceLocation { &self.location } + /// PCI Base Address Register (BAR) manager pub fn bar_manager(&self) -> &BarManager { &self.bar_manager } + /// PCI capabilities pub fn capabilities(&self) -> &Vec { &self.capabilities } + /// Gets the PCI Command pub fn command(&self) -> Command { Command::from_bits_truncate( self.location @@ -44,11 +51,13 @@ impl PciCommonDevice { ) } + /// Sets the PCI Command pub fn set_command(&self, command: Command) { self.location .write16(PciDeviceCommonCfgOffset::Command as u16, command.bits()) } + /// Gets the PCI status pub fn status(&self) -> Status { Status::from_bits_truncate( self.location @@ -84,6 +93,7 @@ impl PciCommonDevice { } } +/// Base Address Registers manager. #[derive(Debug)] pub struct BarManager { /// BARs, the bool indicate whether this bar should exposed to unprivileged part. diff --git a/ostd/src/bus/pci/device_info.rs b/ostd/src/bus/pci/device_info.rs index 05cd91034..8dd60bdeb 100644 --- a/ostd/src/bus/pci/device_info.rs +++ b/ostd/src/bus/pci/device_info.rs @@ -1,19 +1,30 @@ // SPDX-License-Identifier: MPL-2.0 +//! PCI device Information + use core::iter; use super::cfg_space::PciDeviceCommonCfgOffset; use crate::arch::pci::{PCI_ADDRESS_PORT, PCI_DATA_PORT}; +/// PCI device ID #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct PciDeviceId { + /// Vendor ID pub vendor_id: u16, + /// Device ID pub device_id: u16, + /// Revision ID pub revision_id: u8, + /// Programming Interface Byte pub prog_if: u8, + /// Specifies the specific function the device performs. 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, } @@ -41,22 +52,24 @@ impl PciDeviceId { } } +/// PCI device Location #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct PciDeviceLocation { + /// Bus number pub bus: u8, - /// Max 31 + /// Device number with max 31 pub device: u8, - /// Max 7 + /// Deivce number with max 7 pub function: u8, } impl PciDeviceLocation { - pub const MIN_BUS: u8 = 0; - pub const MAX_BUS: u8 = 255; - pub const MIN_DEVICE: u8 = 0; - pub const MAX_DEVICE: u8 = 31; - pub const MIN_FUNCTION: u8 = 0; - pub const MAX_FUNCTION: u8 = 7; + const MIN_BUS: u8 = 0; + const MAX_BUS: u8 = 255; + const MIN_DEVICE: u8 = 0; + const MAX_DEVICE: u8 = 31; + const MIN_FUNCTION: u8 = 0; + const MAX_FUNCTION: u8 = 7; /// By encoding bus, device, and function into u32, user can access a PCI device in x86 by passing in this value. #[inline(always)] pub fn encode_as_x86_address_value(self) -> u32 { diff --git a/ostd/src/bus/pci/mod.rs b/ostd/src/bus/pci/mod.rs index 328bb6654..f21245214 100644 --- a/ostd/src/bus/pci/mod.rs +++ b/ostd/src/bus/pci/mod.rs @@ -61,6 +61,7 @@ pub use device_info::{PciDeviceId, PciDeviceLocation}; use self::{bus::PciBus, common_device::PciCommonDevice}; use crate::sync::Mutex; +/// PCI bus instance pub static PCI_BUS: Mutex = Mutex::new(PciBus::new()); pub(crate) fn init() {