mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 13:26:48 +00:00
Refactor PCI access in OSTD
This commit is contained in:
parent
865003738a
commit
322fc4feff
@ -32,6 +32,7 @@ pub(crate) unsafe fn late_init_on_bsp() {
|
|||||||
crate::boot::smp::boot_all_aps();
|
crate::boot::smp::boot_all_aps();
|
||||||
|
|
||||||
timer::init();
|
timer::init();
|
||||||
|
let _ = pci::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn init_on_ap() {
|
pub(crate) unsafe fn init_on_ap() {
|
||||||
|
@ -1,8 +1,67 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
//! PCI bus io port
|
//! PCI bus access
|
||||||
|
|
||||||
use super::device::io_port::{IoPort, ReadWriteAccess, WriteOnlyAccess};
|
use spin::Once;
|
||||||
|
|
||||||
pub static PCI_ADDRESS_PORT: IoPort<u32, WriteOnlyAccess> = unsafe { IoPort::new(0x0) };
|
use super::boot::DEVICE_TREE;
|
||||||
pub static PCI_DATA_PORT: IoPort<u32, ReadWriteAccess> = unsafe { IoPort::new(0x0) };
|
use crate::{bus::pci::PciDeviceLocation, io::IoMem, mm::VmIoOnce, prelude::*, Error};
|
||||||
|
|
||||||
|
static PCI_BASE_ADDR: Once<IoMem> = Once::new();
|
||||||
|
|
||||||
|
pub(crate) fn write32(location: &PciDeviceLocation, offset: u32, value: u32) -> Result<()> {
|
||||||
|
PCI_BASE_ADDR.get().ok_or(Error::IoError)?.write_once(
|
||||||
|
(encode_as_address_offset(location) | (offset & 0xfc)) as usize,
|
||||||
|
&value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read32(location: &PciDeviceLocation, offset: u32) -> Result<u32> {
|
||||||
|
PCI_BASE_ADDR
|
||||||
|
.get()
|
||||||
|
.ok_or(Error::IoError)?
|
||||||
|
.read_once((encode_as_address_offset(location) | (offset & 0xfc)) as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn has_pci_bus() -> bool {
|
||||||
|
PCI_BASE_ADDR.is_completed()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn init() -> Result<()> {
|
||||||
|
let pci = DEVICE_TREE
|
||||||
|
.get()
|
||||||
|
.unwrap()
|
||||||
|
.find_node("/soc/pci")
|
||||||
|
.ok_or(Error::IoError)?;
|
||||||
|
|
||||||
|
let mut reg = pci.reg().ok_or(Error::IoError)?;
|
||||||
|
|
||||||
|
let Ok(region) = reg.next() else {
|
||||||
|
warn!("PCI node should have exactly one `reg` property, but found zero `reg`s");
|
||||||
|
return Err(Error::IoError);
|
||||||
|
};
|
||||||
|
if reg.next().is_some() {
|
||||||
|
warn!(
|
||||||
|
"PCI node should have exactly one `reg` property, but found {} `reg`s",
|
||||||
|
reg.count() + 2
|
||||||
|
);
|
||||||
|
return Err(Error::IoError);
|
||||||
|
}
|
||||||
|
|
||||||
|
PCI_BASE_ADDR.call_once(|| {
|
||||||
|
IoMem::acquire(
|
||||||
|
(region.starting_address as usize)
|
||||||
|
..(region.starting_address as usize + region.size.unwrap()),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encodes the bus, device, and function into an address offset in the PCI MMIO region.
|
||||||
|
fn encode_as_address_offset(location: &PciDeviceLocation) -> u32 {
|
||||||
|
((location.bus as u32) << 16)
|
||||||
|
| ((location.device as u32) << 11)
|
||||||
|
| ((location.function as u32) << 8)
|
||||||
|
}
|
||||||
|
@ -1,8 +1,35 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
//! PCI bus io port
|
//! PCI bus access
|
||||||
|
|
||||||
use super::device::io_port::{IoPort, ReadWriteAccess, WriteOnlyAccess};
|
use super::device::io_port::{IoPort, ReadWriteAccess, WriteOnlyAccess};
|
||||||
|
use crate::{bus::pci::PciDeviceLocation, prelude::*};
|
||||||
|
|
||||||
pub static PCI_ADDRESS_PORT: IoPort<u32, WriteOnlyAccess> = unsafe { IoPort::new(0x0CF8) };
|
static PCI_ADDRESS_PORT: IoPort<u32, WriteOnlyAccess> = unsafe { IoPort::new(0x0CF8) };
|
||||||
pub static PCI_DATA_PORT: IoPort<u32, ReadWriteAccess> = unsafe { IoPort::new(0x0CFC) };
|
static PCI_DATA_PORT: IoPort<u32, ReadWriteAccess> = unsafe { IoPort::new(0x0CFC) };
|
||||||
|
|
||||||
|
const BIT32_ALIGN_MASK: u32 = 0xFFFC;
|
||||||
|
|
||||||
|
pub(crate) fn write32(location: &PciDeviceLocation, offset: u32, value: u32) -> Result<()> {
|
||||||
|
PCI_ADDRESS_PORT.write(encode_as_port(location) | (offset & BIT32_ALIGN_MASK));
|
||||||
|
PCI_DATA_PORT.write(value.to_le());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read32(location: &PciDeviceLocation, offset: u32) -> Result<u32> {
|
||||||
|
PCI_ADDRESS_PORT.write(encode_as_port(location) | (offset & BIT32_ALIGN_MASK));
|
||||||
|
Ok(PCI_DATA_PORT.read().to_le())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn has_pci_bus() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encodes the bus, device, and function into a port address for use with the PCI I/O port.
|
||||||
|
fn encode_as_port(location: &PciDeviceLocation) -> u32 {
|
||||||
|
// 1 << 31: Configuration enable
|
||||||
|
(1 << 31)
|
||||||
|
| ((location.bus as u32) << 16)
|
||||||
|
| (((location.device as u32) & 0b11111) << 11)
|
||||||
|
| (((location.function as u32) & 0b111) << 8)
|
||||||
|
}
|
||||||
|
@ -16,8 +16,6 @@ pub enum BusProbeError {
|
|||||||
|
|
||||||
/// Initializes the bus
|
/// Initializes the bus
|
||||||
pub(crate) fn init() {
|
pub(crate) fn init() {
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
pci::init();
|
pci::init();
|
||||||
|
|
||||||
mmio::init();
|
mmio::init();
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
use core::iter;
|
use core::iter;
|
||||||
|
|
||||||
use super::cfg_space::PciDeviceCommonCfgOffset;
|
use super::cfg_space::PciDeviceCommonCfgOffset;
|
||||||
use crate::arch::pci::{PCI_ADDRESS_PORT, PCI_DATA_PORT};
|
|
||||||
|
|
||||||
/// PCI device ID
|
/// PCI device ID
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
@ -70,15 +69,6 @@ impl PciDeviceLocation {
|
|||||||
const MAX_DEVICE: u8 = 31;
|
const MAX_DEVICE: u8 = 31;
|
||||||
const MIN_FUNCTION: u8 = 0;
|
const MIN_FUNCTION: u8 = 0;
|
||||||
const MAX_FUNCTION: u8 = 7;
|
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 {
|
|
||||||
// 1 << 31: Configuration enable
|
|
||||||
(1 << 31)
|
|
||||||
| ((self.bus as u32) << 16)
|
|
||||||
| (((self.device as u32) & 0b11111) << 11)
|
|
||||||
| (((self.function as u32) & 0b111) << 8)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator that enumerates all possible PCI device locations.
|
/// Returns an iterator that enumerates all possible PCI device locations.
|
||||||
pub fn all() -> impl Iterator<Item = PciDeviceLocation> {
|
pub fn all() -> impl Iterator<Item = PciDeviceLocation> {
|
||||||
@ -130,9 +120,7 @@ impl PciDeviceLocation {
|
|||||||
(offset & 0b11) == 0,
|
(offset & 0b11) == 0,
|
||||||
"misaligned PCI configuration dword u32 read"
|
"misaligned PCI configuration dword u32 read"
|
||||||
);
|
);
|
||||||
PCI_ADDRESS_PORT
|
crate::arch::pci::read32(self, offset as u32).unwrap()
|
||||||
.write(self.encode_as_x86_address_value() | (offset & Self::BIT32_ALIGN_MASK) as u32);
|
|
||||||
PCI_DATA_PORT.read().to_le()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn write8(&self, offset: u16, val: u8) {
|
pub(super) fn write8(&self, offset: u16, val: u8) {
|
||||||
@ -160,9 +148,6 @@ impl PciDeviceLocation {
|
|||||||
(offset & 0b11) == 0,
|
(offset & 0b11) == 0,
|
||||||
"misaligned PCI configuration dword u32 write"
|
"misaligned PCI configuration dword u32 write"
|
||||||
);
|
);
|
||||||
|
crate::arch::pci::write32(self, offset as u32, val).unwrap()
|
||||||
PCI_ADDRESS_PORT
|
|
||||||
.write(self.encode_as_x86_address_value() | (offset & Self::BIT32_ALIGN_MASK) as u32);
|
|
||||||
PCI_DATA_PORT.write(val.to_le())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,12 +59,16 @@ mod device_info;
|
|||||||
pub use device_info::{PciDeviceId, PciDeviceLocation};
|
pub use device_info::{PciDeviceId, PciDeviceLocation};
|
||||||
|
|
||||||
use self::{bus::PciBus, common_device::PciCommonDevice};
|
use self::{bus::PciBus, common_device::PciCommonDevice};
|
||||||
use crate::sync::Mutex;
|
use crate::{arch::pci::has_pci_bus, sync::Mutex};
|
||||||
|
|
||||||
/// PCI bus instance
|
/// PCI bus instance
|
||||||
pub static PCI_BUS: Mutex<PciBus> = Mutex::new(PciBus::new());
|
pub static PCI_BUS: Mutex<PciBus> = Mutex::new(PciBus::new());
|
||||||
|
|
||||||
pub(crate) fn init() {
|
pub(crate) fn init() {
|
||||||
|
if !has_pci_bus() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut lock = PCI_BUS.lock();
|
let mut lock = PCI_BUS.lock();
|
||||||
for location in PciDeviceLocation::all() {
|
for location in PciDeviceLocation::all() {
|
||||||
let Some(device) = PciCommonDevice::new(location) else {
|
let Some(device) = PciCommonDevice::new(location) else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user