diff --git a/kernel/src/arch/mod.rs b/kernel/src/arch/mod.rs index 2e9a074b..aa6b0495 100644 --- a/kernel/src/arch/mod.rs +++ b/kernel/src/arch/mod.rs @@ -3,7 +3,7 @@ pub mod x86_64; pub use self::x86_64::pci::pci::X86_64PciArch as PciArch; #[cfg(target_arch = "x86_64")] pub use self::x86_64::*; //公开x86_64架构下的函数,使外界接口统一 -use crate::driver::pci::pci::{BusDeviceFunction, PciError, PciRoot, SegmentGroupNumber}; +use crate::driver::pci::pci::{BusDeviceFunction, PciAddr, PciError, PciRoot, SegmentGroupNumber}; /// TraitPciArch Pci架构相关函数,任何架构都应独立实现trait里的函数 pub trait TraitPciArch { /// @brief 读取寄存器值,x86_64架构通过读取两个特定io端口实现 @@ -18,8 +18,8 @@ pub trait TraitPciArch { fn write_config(bus_device_function: &BusDeviceFunction, offset: u8, data: u32); /// @brief PCI域地址到存储器域地址的转换,x86_64架构为一一对应 /// @param address PCI域地址 - /// @return Result 转换结果或出错原因 - fn address_pci_to_address_memory(address: usize) -> Result; + /// @return usize 转换结果 + fn address_pci_to_physical(pci_address: PciAddr) -> usize; /// @brief 获取Segement的root地址,x86_64架构为acpi mcfg表中读取 /// @param segement 组id /// @return Result 转换结果或出错原因 diff --git a/kernel/src/arch/x86_64/pci/pci.rs b/kernel/src/arch/x86_64/pci/pci.rs index 3c3a4405..a6c42477 100644 --- a/kernel/src/arch/x86_64/pci/pci.rs +++ b/kernel/src/arch/x86_64/pci/pci.rs @@ -1,7 +1,7 @@ use crate::arch::TraitPciArch; use crate::driver::acpi::acpi::mcfg_find_segment; use crate::driver::pci::pci::{ - BusDeviceFunction, PciError, PciRoot, SegmentGroupNumber, PORT_PCI_CONFIG_ADDRESS, + BusDeviceFunction, PciAddr, PciError, PciRoot, SegmentGroupNumber, PORT_PCI_CONFIG_ADDRESS, PORT_PCI_CONFIG_DATA, }; use crate::include::bindings::bindings::{ @@ -40,8 +40,8 @@ impl TraitPciArch for X86_64PciArch { } } - fn address_pci_to_address_memory(address: usize) -> Result { - Ok(address) + fn address_pci_to_physical(pci_address: PciAddr) -> usize { + return pci_address.data(); } fn ecam_root(segement: SegmentGroupNumber) -> Result { diff --git a/kernel/src/driver/pci/pci.rs b/kernel/src/driver/pci/pci.rs index 45502545..695989d0 100644 --- a/kernel/src/driver/pci/pci.rs +++ b/kernel/src/driver/pci/pci.rs @@ -11,10 +11,12 @@ use crate::{kdebug, kerror, kinfo, kwarn}; use alloc::vec::Vec; use alloc::{boxed::Box, collections::LinkedList}; use bitflags::bitflags; + use core::{ convert::TryFrom, - fmt::{self, Display, Formatter}, + fmt::{self, Debug, Display, Formatter}, }; + // PCI_DEVICE_LINKEDLIST 添加了读写锁的全局链表,里面存储了检索到的PCI设备结构体 // PCI_ROOT_0 Segment为0的全局PciRoot lazy_static! { @@ -29,6 +31,40 @@ lazy_static! { } }; } +/// PCI域地址 +#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] +#[repr(transparent)] +pub struct PciAddr(usize); + +impl PciAddr { + #[inline(always)] + pub const fn new(address: usize) -> Self { + Self(address) + } + + /// @brief 获取PCI域地址的值 + #[inline(always)] + pub fn data(&self) -> usize { + self.0 + } + + /// @brief 将PCI域地址加上一个偏移量 + #[inline(always)] + pub fn add(self, offset: usize) -> Self { + Self(self.0 + offset) + } + + /// @brief 判断PCI域地址是否按照指定要求对齐 + #[inline(always)] + pub fn check_aligned(&self, align: usize) -> bool { + return self.0 & (align - 1) == 0; + } +} +impl Debug for PciAddr { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "PciAddr({:#x})", self.0) + } +} /// 添加了读写锁的链表,存储PCI设备结构体 pub struct PciDeviceLinkedList { @@ -489,7 +525,7 @@ impl Display for PciRoot { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!( f, - "PCI Root with segement:{}, bus begin at {}, bus end at {}, physical address at {},mapped at {:#x}", + "PCI Root with segement:{}, bus begin at {}, bus end at {}, physical address at {:#x},mapped at {:#x}", self.segement_group_number, self.bus_begin, self.bus_end, self.physical_address_base, self.mmio_base.unwrap() as usize ) } @@ -506,13 +542,14 @@ impl PciRoot { /// @brief 完成物理地址到虚拟地址的映射,并将虚拟地址加入mmio_base变量 /// @return 返回错误或Ok(0) fn map(&mut self) -> Result { - let bus_number = self.bus_end - self.bus_begin + 1; - let bus_number_double = (bus_number + 1) / 2; + //kdebug!("bus_begin={},bus_end={}", self.bus_begin,self.bus_end); + let bus_number = (self.bus_end - self.bus_begin) as u32 + 1; + let bus_number_double = (bus_number - 1) / 2 + 1; //一个bus占据1MB空间,计算全部bus占据空间相对于2MB空间的个数 let mut virtaddress: u64 = 0; let vaddr_ptr = &mut virtaddress as *mut u64; let mut virtsize: u64 = 0; let virtsize_ptr = &mut virtsize as *mut u64; - let size = bus_number_double as u32 * PAGE_2M_SIZE; + let size = bus_number_double * PAGE_2M_SIZE; unsafe { let initial_mm_ptr = &mut initial_mm as *mut mm_struct; if let Err(_) = @@ -978,7 +1015,19 @@ fn pci_check_bus(bus: u8) -> Result { #[no_mangle] pub extern "C" fn rs_pci_init() { pci_init(); - //kdebug!("{}",PCI_ROOT_0.unwrap()); + if PCI_ROOT_0.is_some() { + kdebug!("{}", PCI_ROOT_0.unwrap()); + //以下为ecam的读取寄存器值测试,经测试可正常读取 + // let bus_device_function = BusDeviceFunction { + // bus: 0, + // device: 2, + // function: 0, + // }; + // kdebug!( + // "Ecam read virtio-net device status={:#x}", + // (PCI_ROOT_0.unwrap().read_config(bus_device_function, 4)>>16) as u16 + // ); + } } /// @brief pci初始化函数 pub fn pci_init() { @@ -996,7 +1045,7 @@ pub fn pci_init() { let common_header = box_pci_device.common_header(); match box_pci_device.header_type() { HeaderType::Standard if common_header.status & 0x10 != 0 => { - kinfo!("Found pci standard device with class code ={} subclass={} status={:#x} cap_pointer={:#x} vendor={:#x}, device id={:#x}", common_header.class_code, common_header.subclass, common_header.status, box_pci_device.as_standard_device().unwrap().capabilities_pointer,common_header.vendor_id, common_header.device_id); + kinfo!("Found pci standard device with class code ={} subclass={} status={:#x} cap_pointer={:#x} vendor={:#x}, device id={:#x},bdf={}", common_header.class_code, common_header.subclass, common_header.status, box_pci_device.as_standard_device().unwrap().capabilities_pointer,common_header.vendor_id, common_header.device_id,common_header.bus_device_function); } HeaderType::Standard => { kinfo!( @@ -1055,7 +1104,11 @@ impl BusDeviceFunction { ///实现BusDeviceFunction的Display trait,使其可以直接输出 impl Display for BusDeviceFunction { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{:02x}:{:02x}.{}", self.bus, self.device, self.function) + write!( + f, + "bus {} device {} function{}", + self.bus, self.device, self.function + ) } } /// The location allowed for a memory BAR. @@ -1267,7 +1320,8 @@ pub fn pci_bar_init( address |= u64::from(address_top) << 32; bar_index_ignore = bar_index + 1; //下个bar跳过,因为64位的memory bar覆盖了两个bar } - //kdebug!("address={:#x},size={:#x}",address,size); + let pci_address = PciAddr::new(address as usize); + address = PciArch::address_pci_to_physical(pci_address) as u64; //PCI总线域物理地址转换为存储器域物理地址 unsafe { let vaddr_ptr = &mut virtaddress as *mut u64; let mut virtsize: u64 = 0; diff --git a/kernel/src/driver/virtio/virtio.rs b/kernel/src/driver/virtio/virtio.rs index 3e6d89fc..3e20c687 100644 --- a/kernel/src/driver/virtio/virtio.rs +++ b/kernel/src/driver/virtio/virtio.rs @@ -9,7 +9,6 @@ use crate::libs::rwlock::RwLockWriteGuard; use crate::{kdebug, kerror, kwarn}; use alloc::{boxed::Box, collections::LinkedList}; use virtio_drivers::transport::{DeviceType, Transport}; - const NETWORK_CLASS: u8 = 0x2; const ETHERNET_SUBCLASS: u8 = 0x0; diff --git a/tools/run-qemu.sh b/tools/run-qemu.sh index d7c678fd..5b40c6e9 100644 --- a/tools/run-qemu.sh +++ b/tools/run-qemu.sh @@ -29,7 +29,7 @@ QEMU_RTC_CLOCK="clock=host,base=localtime" QEMU_SERIAL="file:../serial_opt.txt" QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none" -QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -nic user,model=virtio-net-pci -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel}" +QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -nic user,model=virtio-net-pci -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel} -machine q35" QEMU_ARGUMENT="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d -monitor ${QEMU_MONITOR} -d ${qemu_trace_std} "