mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
feat(driver): 把virtio添加到sysfs (#752)
This commit is contained in:
parent
a17651b14b
commit
e32effb150
@ -5,7 +5,7 @@ use x86::msr::{
|
||||
IA32_X2APIC_VERSION,
|
||||
};
|
||||
|
||||
use crate::{kdebug, kinfo};
|
||||
use crate::kinfo;
|
||||
|
||||
use super::{hw_irq::ApicId, LVTRegister, LocalAPIC, LVT};
|
||||
|
||||
@ -55,9 +55,9 @@ impl LocalAPIC for X2Apic {
|
||||
kinfo!("x2APIC EOI broadcast suppression enabled.");
|
||||
}
|
||||
}
|
||||
kdebug!("x2apic: to mask all lvt");
|
||||
// kdebug!("x2apic: to mask all lvt");
|
||||
self.mask_all_lvt();
|
||||
kdebug!("x2apic: all lvt masked");
|
||||
// kdebug!("x2apic: all lvt masked");
|
||||
}
|
||||
true
|
||||
}
|
||||
|
@ -147,12 +147,12 @@ pub trait Bus: Debug + Send + Sync {
|
||||
|
||||
fn resume(&self, device: &Arc<dyn Device>) -> Result<(), SystemError>;
|
||||
|
||||
/// match platform device to platform driver.
|
||||
/// match device to driver.
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// * `device` - platform device
|
||||
/// * `driver` - platform driver
|
||||
/// * `device` - device
|
||||
/// * `driver` - driver
|
||||
///
|
||||
/// ## 返回
|
||||
///
|
||||
|
@ -180,7 +180,7 @@ impl DeviceManager {
|
||||
///
|
||||
/// 如果传递的设备已成功完成对驱动程序的探测,则返回true,否则返回false。
|
||||
pub fn device_is_bound(&self, dev: &Arc<dyn Device>) -> bool {
|
||||
return dev.driver().is_some();
|
||||
return driver_manager().driver_is_bound(dev);
|
||||
}
|
||||
|
||||
/// 把一个驱动绑定到设备上
|
||||
@ -199,6 +199,11 @@ impl DeviceManager {
|
||||
pub fn device_bind_driver(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let r = driver_manager().driver_sysfs_add(dev);
|
||||
if let Err(e) = r {
|
||||
kerror!(
|
||||
"device_bind_driver: driver_sysfs_add failed, dev: '{}', err: {:?}",
|
||||
dev.name(),
|
||||
e
|
||||
);
|
||||
self.device_links_force_bind(dev);
|
||||
driver_manager().driver_bound(dev);
|
||||
return Err(e);
|
||||
@ -606,7 +611,7 @@ impl Attribute for DeviceAttrStateSynced {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DeviceAttrCoredump;
|
||||
pub(super) struct DeviceAttrCoredump;
|
||||
|
||||
impl Attribute for DeviceAttrCoredump {
|
||||
fn name(&self) -> &str {
|
||||
|
@ -3,10 +3,14 @@ use super::{
|
||||
Device, DeviceMatchName, DeviceMatcher, IdTable,
|
||||
};
|
||||
use crate::{
|
||||
driver::base::kobject::KObject,
|
||||
driver::base::{
|
||||
device::{bus::BusNotifyEvent, dd::DeviceAttrCoredump, device_manager},
|
||||
kobject::KObject,
|
||||
},
|
||||
filesystem::sysfs::{sysfs_instance, Attribute, AttributeGroup},
|
||||
};
|
||||
use alloc::{
|
||||
string::ToString,
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
@ -226,8 +230,38 @@ impl DriverManager {
|
||||
}
|
||||
|
||||
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#434
|
||||
pub fn driver_sysfs_add(&self, _dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
todo!("DriverManager::driver_sysfs_add()");
|
||||
pub fn driver_sysfs_add(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
if let Some(bus) = dev.bus().and_then(|bus| bus.upgrade()) {
|
||||
bus.subsystem()
|
||||
.bus_notifier()
|
||||
.call_chain(BusNotifyEvent::BindDriver, Some(dev), None);
|
||||
}
|
||||
let driver_kobj = dev.driver().unwrap() as Arc<dyn KObject>;
|
||||
let device_kobj = dev.clone() as Arc<dyn KObject>;
|
||||
|
||||
let err_remove_device = |e| {
|
||||
sysfs_instance().remove_link(&driver_kobj, dev.name());
|
||||
Err(e)
|
||||
};
|
||||
|
||||
let err_remove_driver = |e| {
|
||||
sysfs_instance().remove_link(&device_kobj, "driver".to_string());
|
||||
err_remove_device(e)
|
||||
};
|
||||
|
||||
sysfs_instance().create_link(Some(&driver_kobj), &device_kobj, device_kobj.name())?;
|
||||
|
||||
if let Err(e) =
|
||||
sysfs_instance().create_link(Some(&device_kobj), &driver_kobj, "driver".to_string())
|
||||
{
|
||||
return err_remove_device(e);
|
||||
}
|
||||
|
||||
if let Err(e) = device_manager().create_file(dev, &DeviceAttrCoredump) {
|
||||
return err_remove_driver(e);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn add_groups(
|
||||
|
@ -22,6 +22,7 @@ use super::{
|
||||
driver::Driver,
|
||||
Device,
|
||||
},
|
||||
kobject::KObject,
|
||||
kset::KSet,
|
||||
};
|
||||
|
||||
@ -82,6 +83,10 @@ impl SubSysPrivate {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn name(&self) -> String {
|
||||
return self.subsys.name();
|
||||
}
|
||||
|
||||
pub fn subsys(&self) -> Arc<KSet> {
|
||||
return self.subsys.clone();
|
||||
}
|
||||
|
@ -4,14 +4,15 @@ use crate::{
|
||||
arch::rand::rand,
|
||||
driver::{
|
||||
base::{
|
||||
device::{bus::Bus, driver::Driver, Device, IdTable},
|
||||
class::Class,
|
||||
device::{bus::Bus, driver::Driver, Device, DeviceType, IdTable},
|
||||
kobject::{KObjType, KObject, KObjectState},
|
||||
},
|
||||
net::NetDriver,
|
||||
net::NetDevice,
|
||||
},
|
||||
kinfo,
|
||||
libs::spinlock::SpinLock,
|
||||
net::{generate_iface_id, NET_DRIVERS},
|
||||
net::{generate_iface_id, NET_DEVICES},
|
||||
time::Instant,
|
||||
};
|
||||
use alloc::{
|
||||
@ -205,33 +206,49 @@ impl Debug for E1000EInterface {
|
||||
}
|
||||
}
|
||||
|
||||
impl Driver for E1000EInterface {
|
||||
fn id_table(&self) -> Option<IdTable> {
|
||||
impl Device for E1000EInterface {
|
||||
fn dev_type(&self) -> DeviceType {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn add_device(&self, _device: Arc<dyn Device>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn delete_device(&self, _device: &Arc<dyn Device>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn devices(&self) -> alloc::vec::Vec<Arc<dyn Device>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
fn id_table(&self) -> IdTable {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_class(&self, _class: Option<Weak<dyn Class>>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_driver(&self, _driver: Option<Weak<dyn Driver>>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn is_dead(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn can_match(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_can_match(&self, _can_match: bool) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn state_synced(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl NetDriver for E1000EInterface {
|
||||
impl NetDevice for E1000EInterface {
|
||||
fn mac(&self) -> smoltcp::wire::EthernetAddress {
|
||||
let mac = self.driver.inner.lock().mac_address();
|
||||
return smoltcp::wire::EthernetAddress::from_bytes(&mac);
|
||||
@ -347,7 +364,7 @@ pub fn e1000e_driver_init(device: E1000EDevice) {
|
||||
let driver = E1000EDriver::new(device);
|
||||
let iface = E1000EInterface::new(driver);
|
||||
// 将网卡的接口信息注册到全局的网卡接口信息表中
|
||||
NET_DRIVERS
|
||||
NET_DEVICES
|
||||
.write_irqsave()
|
||||
.insert(iface.nic_id(), iface.clone());
|
||||
kinfo!("e1000e driver init successfully!\tMAC: [{}]", mac);
|
||||
|
@ -4,7 +4,7 @@ use smoltcp::{
|
||||
wire::{self, EthernetAddress},
|
||||
};
|
||||
|
||||
use super::base::device::driver::Driver;
|
||||
use super::base::device::Device;
|
||||
use crate::libs::spinlock::SpinLock;
|
||||
use system_error::SystemError;
|
||||
|
||||
@ -13,7 +13,7 @@ pub mod e1000e;
|
||||
pub mod irq_handle;
|
||||
pub mod virtio_net;
|
||||
|
||||
pub trait NetDriver: Driver {
|
||||
pub trait NetDevice: Device {
|
||||
/// @brief 获取网卡的MAC地址
|
||||
fn mac(&self) -> EthernetAddress;
|
||||
|
||||
|
@ -1,123 +1,206 @@
|
||||
use core::{
|
||||
any::Any,
|
||||
cell::UnsafeCell,
|
||||
fmt::Debug,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use alloc::{
|
||||
string::String,
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use smoltcp::{iface, phy, wire};
|
||||
use virtio_drivers::{device::net::VirtIONet, transport::Transport};
|
||||
use unified_init::macros::unified_init;
|
||||
use virtio_drivers::device::net::VirtIONet;
|
||||
|
||||
use super::NetDriver;
|
||||
use super::NetDevice;
|
||||
use crate::{
|
||||
arch::rand::rand,
|
||||
driver::{
|
||||
base::{
|
||||
device::{bus::Bus, driver::Driver, Device, DeviceId, IdTable},
|
||||
kobject::{KObjType, KObject, KObjectState},
|
||||
class::Class,
|
||||
device::{
|
||||
bus::Bus,
|
||||
driver::{Driver, DriverCommonData},
|
||||
Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
},
|
||||
virtio::{
|
||||
irq::virtio_irq_manager,
|
||||
sysfs::{virtio_bus, virtio_device_manager, virtio_driver_manager},
|
||||
transport::VirtIOTransport,
|
||||
virtio_impl::HalImpl,
|
||||
VirtIODevice, VirtIODeviceIndex, VirtIODriver, VIRTIO_VENDOR_ID,
|
||||
},
|
||||
virtio::{irq::virtio_irq_manager, virtio_impl::HalImpl, VirtIODevice},
|
||||
},
|
||||
exception::{irqdesc::IrqReturn, IrqNumber},
|
||||
kerror, kinfo,
|
||||
libs::spinlock::SpinLock,
|
||||
net::{generate_iface_id, net_core::poll_ifaces_try_lock_onetime, NET_DRIVERS},
|
||||
filesystem::kernfs::KernFSInode,
|
||||
init::initcall::INITCALL_POSTCORE,
|
||||
kerror,
|
||||
libs::{
|
||||
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
net::{generate_iface_id, net_core::poll_ifaces_try_lock_onetime, NET_DEVICES},
|
||||
time::Instant,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
|
||||
/// @brief Virtio网络设备驱动(加锁)
|
||||
pub struct VirtioNICDriver<T: Transport> {
|
||||
pub inner: Arc<SpinLock<VirtIONet<HalImpl, T, 2>>>,
|
||||
static mut VIRTIO_NET_DRIVER: Option<Arc<VirtIONetDriver>> = None;
|
||||
|
||||
const DEVICE_NAME: &str = "virtio_net";
|
||||
|
||||
#[inline(always)]
|
||||
fn virtio_net_driver() -> Arc<VirtIONetDriver> {
|
||||
unsafe { VIRTIO_NET_DRIVER.as_ref().unwrap().clone() }
|
||||
}
|
||||
|
||||
impl<T: Transport> Clone for VirtioNICDriver<T> {
|
||||
fn clone(&self) -> Self {
|
||||
return VirtioNICDriver {
|
||||
inner: self.inner.clone(),
|
||||
};
|
||||
pub struct VirtIoNetImpl {
|
||||
inner: VirtIONet<HalImpl, VirtIOTransport, 2>,
|
||||
}
|
||||
|
||||
impl VirtIoNetImpl {
|
||||
const fn new(inner: VirtIONet<HalImpl, VirtIOTransport, 2>) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
|
||||
/// 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。
|
||||
///
|
||||
/// 由于smoltcp的设计,导致需要在poll的时候获取网卡驱动的可变引用,
|
||||
/// 同时需要在token的consume里面获取可变引用。为了避免双重加锁,所以需要这个包裹器。
|
||||
struct VirtioNICDriverWrapper<T: Transport>(UnsafeCell<VirtioNICDriver<T>>);
|
||||
unsafe impl<T: Transport> Send for VirtioNICDriverWrapper<T> {}
|
||||
unsafe impl<T: Transport> Sync for VirtioNICDriverWrapper<T> {}
|
||||
impl Deref for VirtIoNetImpl {
|
||||
type Target = VirtIONet<HalImpl, VirtIOTransport, 2>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transport> Deref for VirtioNICDriverWrapper<T> {
|
||||
type Target = VirtioNICDriver<T>;
|
||||
impl DerefMut for VirtIoNetImpl {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for VirtIoNetImpl {}
|
||||
unsafe impl Sync for VirtIoNetImpl {}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct VirtIONicDeviceInnerWrapper(UnsafeCell<VirtIONicDeviceInner>);
|
||||
unsafe impl Send for VirtIONicDeviceInnerWrapper {}
|
||||
unsafe impl Sync for VirtIONicDeviceInnerWrapper {}
|
||||
|
||||
impl Deref for VirtIONicDeviceInnerWrapper {
|
||||
type Target = VirtIONicDeviceInner;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &*self.0.get() }
|
||||
}
|
||||
}
|
||||
impl<T: Transport> DerefMut for VirtioNICDriverWrapper<T> {
|
||||
impl DerefMut for VirtIONicDeviceInnerWrapper {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { &mut *self.0.get() }
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
impl<T: Transport> VirtioNICDriverWrapper<T> {
|
||||
fn force_get_mut(&self) -> &mut VirtioNICDriver<T> {
|
||||
impl VirtIONicDeviceInnerWrapper {
|
||||
fn force_get_mut(&self) -> &mut <VirtIONicDeviceInnerWrapper as Deref>::Target {
|
||||
unsafe { &mut *self.0.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transport> Debug for VirtioNICDriver<T> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("VirtioNICDriver").finish()
|
||||
/// Virtio网络设备驱动(加锁)
|
||||
pub struct VirtIONicDeviceInner {
|
||||
pub inner: Arc<SpinLock<VirtIoNetImpl>>,
|
||||
}
|
||||
|
||||
impl Clone for VirtIONicDeviceInner {
|
||||
fn clone(&self) -> Self {
|
||||
return VirtIONicDeviceInner {
|
||||
inner: self.inner.clone(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VirtioInterface<T: Transport> {
|
||||
driver: VirtioNICDriverWrapper<T>,
|
||||
iface_id: usize,
|
||||
iface: SpinLock<iface::Interface>,
|
||||
name: String,
|
||||
dev_id: Arc<DeviceId>,
|
||||
impl Debug for VirtIONicDeviceInner {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("VirtIONicDriver").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transport> Debug for VirtioInterface<T> {
|
||||
#[cast_to([sync] VirtIODevice)]
|
||||
pub struct VirtioInterface {
|
||||
device_inner: VirtIONicDeviceInnerWrapper,
|
||||
iface_id: usize,
|
||||
iface_name: String,
|
||||
dev_id: Arc<DeviceId>,
|
||||
iface: SpinLock<iface::Interface>,
|
||||
inner: SpinLock<InnerVirtIOInterface>,
|
||||
locked_kobj_state: LockedKObjectState,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InnerVirtIOInterface {
|
||||
name: Option<String>,
|
||||
virtio_index: Option<VirtIODeviceIndex>,
|
||||
device_common: DeviceCommonData,
|
||||
kobj_common: KObjectCommonData,
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for VirtioInterface {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("VirtioInterface")
|
||||
.field("driver", self.driver.deref())
|
||||
.field("iface_id", &self.iface_id)
|
||||
.field("iface", &"smoltcp::iface::Interface")
|
||||
.field("name", &self.name)
|
||||
.field("iface_name", &self.iface_name)
|
||||
.field("dev_id", &self.dev_id)
|
||||
.field("inner", &self.inner)
|
||||
.field("locked_kobj_state", &self.locked_kobj_state)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transport> VirtioInterface<T> {
|
||||
pub fn new(mut driver: VirtioNICDriver<T>, dev_id: Arc<DeviceId>) -> Arc<Self> {
|
||||
impl VirtioInterface {
|
||||
pub fn new(mut device_inner: VirtIONicDeviceInner, dev_id: Arc<DeviceId>) -> Arc<Self> {
|
||||
let iface_id = generate_iface_id();
|
||||
let mut iface_config = iface::Config::new(wire::HardwareAddress::Ethernet(
|
||||
wire::EthernetAddress(driver.inner.lock().mac_address()),
|
||||
wire::EthernetAddress(device_inner.inner.lock().mac_address()),
|
||||
));
|
||||
iface_config.random_seed = rand() as u64;
|
||||
|
||||
let iface = iface::Interface::new(iface_config, &mut driver, Instant::now().into());
|
||||
let iface = iface::Interface::new(iface_config, &mut device_inner, Instant::now().into());
|
||||
|
||||
let driver: VirtioNICDriverWrapper<T> = VirtioNICDriverWrapper(UnsafeCell::new(driver));
|
||||
let result = Arc::new(VirtioInterface {
|
||||
driver,
|
||||
device_inner: VirtIONicDeviceInnerWrapper(UnsafeCell::new(device_inner)),
|
||||
iface_id,
|
||||
locked_kobj_state: LockedKObjectState::default(),
|
||||
iface: SpinLock::new(iface),
|
||||
name: format!("eth{}", iface_id),
|
||||
iface_name: format!("eth{}", iface_id),
|
||||
dev_id,
|
||||
inner: SpinLock::new(InnerVirtIOInterface {
|
||||
name: None,
|
||||
virtio_index: None,
|
||||
device_common: DeviceCommonData::default(),
|
||||
kobj_common: KObjectCommonData::default(),
|
||||
}),
|
||||
});
|
||||
|
||||
result.inner().device_common.driver =
|
||||
Some(Arc::downgrade(&virtio_net_driver()) as Weak<dyn Driver>);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn inner(&self) -> SpinLockGuard<InnerVirtIOInterface> {
|
||||
return self.inner.lock();
|
||||
}
|
||||
|
||||
/// 获取网卡接口的名称
|
||||
#[allow(dead_code)]
|
||||
pub fn iface_name(&self) -> String {
|
||||
self.iface_name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transport + 'static> VirtIODevice for VirtioInterface<T> {
|
||||
impl VirtIODevice for VirtioInterface {
|
||||
fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError> {
|
||||
poll_ifaces_try_lock_onetime().ok();
|
||||
return Ok(IrqReturn::Handled);
|
||||
@ -126,46 +209,133 @@ impl<T: Transport + 'static> VirtIODevice for VirtioInterface<T> {
|
||||
fn dev_id(&self) -> &Arc<DeviceId> {
|
||||
return &self.dev_id;
|
||||
}
|
||||
}
|
||||
fn set_virtio_device_index(&self, index: VirtIODeviceIndex) {
|
||||
self.inner().virtio_index = Some(index);
|
||||
}
|
||||
|
||||
impl<T: Transport> Drop for VirtioInterface<T> {
|
||||
fn drop(&mut self) {
|
||||
// 从全局的网卡接口信息表中删除这个网卡的接口信息
|
||||
NET_DRIVERS.write_irqsave().remove(&self.iface_id);
|
||||
fn virtio_device_index(&self) -> Option<VirtIODeviceIndex> {
|
||||
return self.inner().virtio_index;
|
||||
}
|
||||
|
||||
fn set_device_name(&self, name: String) {
|
||||
self.inner().name = Some(name);
|
||||
}
|
||||
|
||||
fn device_name(&self) -> String {
|
||||
self.inner()
|
||||
.name
|
||||
.clone()
|
||||
.unwrap_or_else(|| "virtio_net".to_string())
|
||||
}
|
||||
|
||||
fn device_type_id(&self) -> u32 {
|
||||
virtio_drivers::transport::DeviceType::Network as u32
|
||||
}
|
||||
|
||||
fn vendor(&self) -> u32 {
|
||||
VIRTIO_VENDOR_ID.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static + Transport> VirtioNICDriver<T> {
|
||||
pub fn new(driver_net: VirtIONet<HalImpl, T, 2>) -> Self {
|
||||
impl Drop for VirtioInterface {
|
||||
fn drop(&mut self) {
|
||||
// 从全局的网卡接口信息表中删除这个网卡的接口信息
|
||||
NET_DEVICES.write_irqsave().remove(&self.iface_id);
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for VirtioInterface {
|
||||
fn dev_type(&self) -> DeviceType {
|
||||
DeviceType::Net
|
||||
}
|
||||
|
||||
fn id_table(&self) -> IdTable {
|
||||
IdTable::new(DEVICE_NAME.to_string(), None)
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
self.inner().device_common.bus.clone()
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
|
||||
self.inner().device_common.bus = bus;
|
||||
}
|
||||
|
||||
fn class(&self) -> Option<Arc<dyn Class>> {
|
||||
let mut guard = self.inner();
|
||||
let r = guard.device_common.class.clone()?.upgrade();
|
||||
if r.is_none() {
|
||||
guard.device_common.class = None;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
fn set_class(&self, class: Option<Weak<dyn Class>>) {
|
||||
self.inner().device_common.class = class;
|
||||
}
|
||||
|
||||
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||
let r = self.inner().device_common.driver.clone()?.upgrade();
|
||||
if r.is_none() {
|
||||
self.inner().device_common.driver = None;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
|
||||
self.inner().device_common.driver = driver;
|
||||
}
|
||||
|
||||
fn is_dead(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn can_match(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn set_can_match(&self, can_match: bool) {
|
||||
self.inner().device_common.can_match = can_match;
|
||||
}
|
||||
|
||||
fn state_synced(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtIONicDeviceInner {
|
||||
pub fn new(driver_net: VirtIONet<HalImpl, VirtIOTransport, 2>) -> Self {
|
||||
let mut iface_config = iface::Config::new(wire::HardwareAddress::Ethernet(
|
||||
wire::EthernetAddress(driver_net.mac_address()),
|
||||
));
|
||||
|
||||
iface_config.random_seed = rand() as u64;
|
||||
|
||||
let inner: Arc<SpinLock<VirtIONet<HalImpl, T, 2>>> = Arc::new(SpinLock::new(driver_net));
|
||||
let result = VirtioNICDriver { inner };
|
||||
let inner = Arc::new(SpinLock::new(VirtIoNetImpl::new(driver_net)));
|
||||
let result = VirtIONicDeviceInner { inner };
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VirtioNetToken<T: Transport> {
|
||||
driver: VirtioNICDriver<T>,
|
||||
pub struct VirtioNetToken {
|
||||
driver: VirtIONicDeviceInner,
|
||||
rx_buffer: Option<virtio_drivers::device::net::RxBuffer>,
|
||||
}
|
||||
|
||||
impl<T: Transport> VirtioNetToken<T> {
|
||||
impl VirtioNetToken {
|
||||
pub fn new(
|
||||
driver: VirtioNICDriver<T>,
|
||||
driver: VirtIONicDeviceInner,
|
||||
rx_buffer: Option<virtio_drivers::device::net::RxBuffer>,
|
||||
) -> Self {
|
||||
return Self { driver, rx_buffer };
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transport> phy::Device for VirtioNICDriver<T> {
|
||||
type RxToken<'a> = VirtioNetToken<T> where Self: 'a;
|
||||
type TxToken<'a> = VirtioNetToken<T> where Self: 'a;
|
||||
impl phy::Device for VirtIONicDeviceInner {
|
||||
type RxToken<'a> = VirtioNetToken where Self: 'a;
|
||||
type TxToken<'a> = VirtioNetToken where Self: 'a;
|
||||
|
||||
fn receive(
|
||||
&mut self,
|
||||
@ -206,13 +376,12 @@ impl<T: Transport> phy::Device for VirtioNICDriver<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transport> phy::TxToken for VirtioNetToken<T> {
|
||||
impl phy::TxToken for VirtioNetToken {
|
||||
fn consume<R, F>(self, len: usize, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> R,
|
||||
{
|
||||
// // 为了线程安全,这里需要对VirtioNet进行加【写锁】,以保证对设备的互斥访问。
|
||||
|
||||
let mut driver_net = self.driver.inner.lock();
|
||||
let mut tx_buf = driver_net.new_tx_buffer(len);
|
||||
let result = f(tx_buf.packet_mut());
|
||||
@ -221,7 +390,7 @@ impl<T: Transport> phy::TxToken for VirtioNetToken<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transport> phy::RxToken for VirtioNetToken<T> {
|
||||
impl phy::RxToken for VirtioNetToken {
|
||||
fn consume<R, F>(self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> R,
|
||||
@ -239,9 +408,9 @@ impl<T: Transport> phy::RxToken for VirtioNetToken<T> {
|
||||
}
|
||||
|
||||
/// @brief virtio-net 驱动的初始化与测试
|
||||
pub fn virtio_net<T: Transport + 'static>(transport: T, dev_id: Arc<DeviceId>) {
|
||||
let driver_net: VirtIONet<HalImpl, T, 2> =
|
||||
match VirtIONet::<HalImpl, T, 2>::new(transport, 4096) {
|
||||
pub fn virtio_net(transport: VirtIOTransport, dev_id: Arc<DeviceId>) {
|
||||
let driver_net: VirtIONet<HalImpl, VirtIOTransport, 2> =
|
||||
match VirtIONet::<HalImpl, VirtIOTransport, 2>::new(transport, 4096) {
|
||||
Ok(net) => net,
|
||||
Err(_) => {
|
||||
kerror!("VirtIONet init failed");
|
||||
@ -249,53 +418,17 @@ pub fn virtio_net<T: Transport + 'static>(transport: T, dev_id: Arc<DeviceId>) {
|
||||
}
|
||||
};
|
||||
let mac = wire::EthernetAddress::from_bytes(&driver_net.mac_address());
|
||||
let driver: VirtioNICDriver<T> = VirtioNICDriver::new(driver_net);
|
||||
let iface = VirtioInterface::new(driver, dev_id);
|
||||
let name = iface.name.clone();
|
||||
// 将网卡的接口信息注册到全局的网卡接口信息表中
|
||||
NET_DRIVERS
|
||||
.write_irqsave()
|
||||
.insert(iface.nic_id(), iface.clone());
|
||||
|
||||
virtio_irq_manager()
|
||||
.register_device(iface.clone())
|
||||
.expect("Register virtio net failed");
|
||||
kinfo!(
|
||||
"Virtio-net driver init successfully!\tNetDevID: [{}], MAC: [{}]",
|
||||
name,
|
||||
mac
|
||||
);
|
||||
let dev_inner = VirtIONicDeviceInner::new(driver_net);
|
||||
let iface = VirtioInterface::new(dev_inner, dev_id);
|
||||
kdebug!("To add virtio net: {}, mac: {}", iface.device_name(), mac);
|
||||
virtio_device_manager()
|
||||
.device_add(iface.clone() as Arc<dyn VirtIODevice>)
|
||||
.expect("Add virtio net failed");
|
||||
}
|
||||
|
||||
impl<T: Transport + 'static> Driver for VirtioInterface<T> {
|
||||
fn id_table(&self) -> Option<IdTable> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn add_device(&self, _device: Arc<dyn Device>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn delete_device(&self, _device: &Arc<dyn Device>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn devices(&self) -> alloc::vec::Vec<Arc<dyn Device>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transport + 'static> NetDriver for VirtioInterface<T> {
|
||||
impl NetDevice for VirtioInterface {
|
||||
fn mac(&self) -> wire::EthernetAddress {
|
||||
let mac: [u8; 6] = self.driver.inner.lock().mac_address();
|
||||
let mac: [u8; 6] = self.device_inner.inner.lock().mac_address();
|
||||
return wire::EthernetAddress::from_bytes(&mac);
|
||||
}
|
||||
|
||||
@ -306,7 +439,7 @@ impl<T: Transport + 'static> NetDriver for VirtioInterface<T> {
|
||||
|
||||
#[inline]
|
||||
fn name(&self) -> String {
|
||||
return self.name.clone();
|
||||
return self.iface_name.clone();
|
||||
}
|
||||
|
||||
fn update_ip_addrs(&self, ip_addrs: &[wire::IpCidr]) -> Result<(), SystemError> {
|
||||
@ -331,7 +464,7 @@ impl<T: Transport + 'static> NetDriver for VirtioInterface<T> {
|
||||
fn poll(&self, sockets: &mut iface::SocketSet) -> Result<(), SystemError> {
|
||||
let timestamp: smoltcp::time::Instant = Instant::now().into();
|
||||
let mut guard = self.iface.lock();
|
||||
let poll_res = guard.poll(timestamp, self.driver.force_get_mut(), sockets);
|
||||
let poll_res = guard.poll(timestamp, self.device_inner.force_get_mut(), sockets);
|
||||
// todo: notify!!!
|
||||
// kdebug!("Virtio Interface poll:{poll_res}");
|
||||
if poll_res {
|
||||
@ -349,71 +482,235 @@ impl<T: Transport + 'static> NetDriver for VirtioInterface<T> {
|
||||
// }
|
||||
}
|
||||
|
||||
impl<T: Transport + 'static> KObject for VirtioInterface<T> {
|
||||
impl KObject for VirtioInterface {
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn set_inode(&self, _inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
|
||||
todo!()
|
||||
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
|
||||
self.inner().kobj_common.kern_inode = inode;
|
||||
}
|
||||
|
||||
fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
|
||||
todo!()
|
||||
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||
self.inner().kobj_common.kern_inode.clone()
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
|
||||
todo!()
|
||||
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||
self.inner().kobj_common.parent.clone()
|
||||
}
|
||||
|
||||
fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) {
|
||||
todo!()
|
||||
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
|
||||
self.inner().kobj_common.parent = parent;
|
||||
}
|
||||
|
||||
fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
|
||||
todo!()
|
||||
fn kset(&self) -> Option<Arc<KSet>> {
|
||||
self.inner().kobj_common.kset.clone()
|
||||
}
|
||||
|
||||
fn set_kset(&self, _kset: Option<Arc<crate::driver::base::kset::KSet>>) {
|
||||
todo!()
|
||||
fn set_kset(&self, kset: Option<Arc<KSet>>) {
|
||||
self.inner().kobj_common.kset = kset;
|
||||
}
|
||||
|
||||
fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
|
||||
todo!()
|
||||
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||
self.inner().kobj_common.kobj_type
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
self.name.clone()
|
||||
self.device_name()
|
||||
}
|
||||
|
||||
fn set_name(&self, _name: String) {
|
||||
todo!()
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fn kobj_state(
|
||||
&self,
|
||||
) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
|
||||
todo!()
|
||||
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||
self.locked_kobj_state.read()
|
||||
}
|
||||
|
||||
fn kobj_state_mut(
|
||||
&self,
|
||||
) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
|
||||
todo!()
|
||||
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||
self.locked_kobj_state.write()
|
||||
}
|
||||
|
||||
fn set_kobj_state(&self, _state: KObjectState) {
|
||||
todo!()
|
||||
fn set_kobj_state(&self, state: KObjectState) {
|
||||
*self.locked_kobj_state.write() = state;
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
||||
todo!()
|
||||
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
|
||||
self.inner().kobj_common.kobj_type = ktype;
|
||||
}
|
||||
}
|
||||
|
||||
// 向编译器保证,VirtioNICDriver在线程之间是安全的.
|
||||
// 由于smoltcp只会在token内真正操作网卡设备,并且在VirtioNetToken的consume
|
||||
// 方法内,会对VirtioNet进行加【写锁】,因此,能够保证对设备操作的的互斥访问,
|
||||
// 因此VirtioNICDriver在线程之间是安全的。
|
||||
// unsafe impl<T: Transport> Sync for VirtioNICDriver<T> {}
|
||||
// unsafe impl<T: Transport> Send for VirtioNICDriver<T> {}
|
||||
#[unified_init(INITCALL_POSTCORE)]
|
||||
fn virtio_net_driver_init() -> Result<(), SystemError> {
|
||||
let driver = VirtIONetDriver::new();
|
||||
virtio_driver_manager()
|
||||
.register(driver.clone() as Arc<dyn VirtIODriver>)
|
||||
.expect("Add virtio net driver failed");
|
||||
unsafe {
|
||||
VIRTIO_NET_DRIVER = Some(driver);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
#[derive(Debug)]
|
||||
#[cast_to([sync] VirtIODriver)]
|
||||
struct VirtIONetDriver {
|
||||
inner: SpinLock<InnerVirtIODriver>,
|
||||
kobj_state: LockedKObjectState,
|
||||
}
|
||||
|
||||
impl VirtIONetDriver {
|
||||
pub fn new() -> Arc<Self> {
|
||||
let inner = InnerVirtIODriver {
|
||||
driver_common: DriverCommonData::default(),
|
||||
kobj_common: KObjectCommonData::default(),
|
||||
};
|
||||
Arc::new(VirtIONetDriver {
|
||||
inner: SpinLock::new(inner),
|
||||
kobj_state: LockedKObjectState::default(),
|
||||
})
|
||||
}
|
||||
|
||||
fn inner(&self) -> SpinLockGuard<InnerVirtIODriver> {
|
||||
return self.inner.lock();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InnerVirtIODriver {
|
||||
driver_common: DriverCommonData,
|
||||
kobj_common: KObjectCommonData,
|
||||
}
|
||||
|
||||
impl VirtIODriver for VirtIONetDriver {
|
||||
fn probe(&self, device: &Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
|
||||
let iface = device
|
||||
.clone()
|
||||
.arc_any()
|
||||
.downcast::<VirtioInterface>()
|
||||
.map_err(|_| {
|
||||
kerror!(
|
||||
"VirtIONetDriver::probe() failed: device is not a VirtioInterface. Device: '{:?}'",
|
||||
device.name()
|
||||
);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
|
||||
// 将网卡的接口信息注册到全局的网卡接口信息表中
|
||||
NET_DEVICES
|
||||
.write_irqsave()
|
||||
.insert(iface.nic_id(), iface.clone());
|
||||
|
||||
virtio_irq_manager()
|
||||
.register_device(iface.clone())
|
||||
.expect("Register virtio net failed");
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
impl Driver for VirtIONetDriver {
|
||||
fn id_table(&self) -> Option<IdTable> {
|
||||
Some(IdTable::new(DEVICE_NAME.to_string(), None))
|
||||
}
|
||||
|
||||
fn add_device(&self, device: Arc<dyn Device>) {
|
||||
let iface = device
|
||||
.arc_any()
|
||||
.downcast::<VirtioInterface>()
|
||||
.expect("VirtIONetDriver::add_device() failed: device is not a VirtioInterface");
|
||||
|
||||
self.inner()
|
||||
.driver_common
|
||||
.devices
|
||||
.push(iface as Arc<dyn Device>);
|
||||
}
|
||||
|
||||
fn delete_device(&self, device: &Arc<dyn Device>) {
|
||||
let _iface = device
|
||||
.clone()
|
||||
.arc_any()
|
||||
.downcast::<VirtioInterface>()
|
||||
.expect("VirtIONetDriver::delete_device() failed: device is not a VirtioInterface");
|
||||
|
||||
let mut guard = self.inner();
|
||||
let index = guard
|
||||
.driver_common
|
||||
.devices
|
||||
.iter()
|
||||
.position(|dev| Arc::ptr_eq(device, dev))
|
||||
.expect("VirtIONetDriver::delete_device() failed: device not found");
|
||||
|
||||
guard.driver_common.devices.remove(index);
|
||||
}
|
||||
|
||||
fn devices(&self) -> Vec<Arc<dyn Device>> {
|
||||
self.inner().driver_common.devices.clone()
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
Some(Arc::downgrade(&virtio_bus()) as Weak<dyn Bus>)
|
||||
}
|
||||
|
||||
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
impl KObject for VirtIONetDriver {
|
||||
fn as_any_ref(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
|
||||
self.inner().kobj_common.kern_inode = inode;
|
||||
}
|
||||
|
||||
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||
self.inner().kobj_common.kern_inode.clone()
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||
self.inner().kobj_common.parent.clone()
|
||||
}
|
||||
|
||||
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
|
||||
self.inner().kobj_common.parent = parent;
|
||||
}
|
||||
|
||||
fn kset(&self) -> Option<Arc<KSet>> {
|
||||
self.inner().kobj_common.kset.clone()
|
||||
}
|
||||
|
||||
fn set_kset(&self, kset: Option<Arc<KSet>>) {
|
||||
self.inner().kobj_common.kset = kset;
|
||||
}
|
||||
|
||||
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||
self.inner().kobj_common.kobj_type
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
|
||||
self.inner().kobj_common.kobj_type = ktype;
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
DEVICE_NAME.to_string()
|
||||
}
|
||||
|
||||
fn set_name(&self, _name: String) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||
self.kobj_state.read()
|
||||
}
|
||||
|
||||
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||
self.kobj_state.write()
|
||||
}
|
||||
|
||||
fn set_kobj_state(&self, state: KObjectState) {
|
||||
*self.kobj_state.write() = state;
|
||||
}
|
||||
}
|
||||
|
@ -95,11 +95,45 @@ impl PciDeviceLinkedList {
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 在链表中寻找满足条件的PCI设备结构体并返回其可变引用
|
||||
/// @param list 链表的写锁守卫
|
||||
/// @param class_code 寄存器值
|
||||
/// @param subclass 寄存器值,与class_code一起确定设备类型
|
||||
/// @return Vec<&'a mut Box<(dyn PciDeviceStructure) 包含链表中所有满足条件的PCI结构体的可变引用的容器
|
||||
/// # 获取具有特定供应商ID的PCI设备结构的引用
|
||||
///
|
||||
/// 这个函数通过供应商ID搜索PCI设备结构列表,并返回匹配该ID的所有设备结构的引用。
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - list: 一个可变的PCI设备结构链表,类型为`&'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>`。
|
||||
/// - vendor_id: 要查找的PCI供应商ID,类型为`u16`。
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// - 返回匹配的供应商ID的PCI设备结构的引用。
|
||||
pub fn get_pci_device_structures_mut_by_vendor_id<'a>(
|
||||
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
||||
vendor_id: u16,
|
||||
) -> Vec<&'a mut Box<(dyn PciDeviceStructure)>> {
|
||||
let mut result = Vec::new();
|
||||
for box_pci_device_structure in list.iter_mut() {
|
||||
let common_header = (*box_pci_device_structure).common_header();
|
||||
if common_header.vendor_id == vendor_id {
|
||||
result.push(box_pci_device_structure);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// # get_pci_device_structure_mut - 在链表中寻找满足条件的PCI设备结构体并返回其可变引用
|
||||
///
|
||||
/// 该函数遍历给定的PCI设备链表,寻找其common_header中class_code和subclass字段与给定值匹配的设备结构体。
|
||||
/// 对于每一个匹配的设备结构体,函数返回一个可变引用。
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>> — 链表的写锁守卫,用于访问和遍历PCI设备链表。
|
||||
/// - class_code: u8 — PCI设备class code寄存器值,用于分类设备的功能。
|
||||
/// - subclass: u8 — PCI设备subclass寄存器值,与class_code一起确定设备的子类型。
|
||||
///
|
||||
/// ## 返回值
|
||||
/// - 包含链表中所有满足条件的PCI结构体的可变引用的容器。
|
||||
pub fn get_pci_device_structure_mut<'a>(
|
||||
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
||||
class_code: u8,
|
||||
@ -114,11 +148,20 @@ pub fn get_pci_device_structure_mut<'a>(
|
||||
}
|
||||
result
|
||||
}
|
||||
/// @brief 在链表中寻找满足条件的PCI设备结构体并返回其不可变引用
|
||||
/// @param list 链表的读锁守卫
|
||||
/// @param class_code 寄存器值
|
||||
/// @param subclass 寄存器值,与class_code一起确定设备类型
|
||||
/// @return Vec<&'a Box<(dyn PciDeviceStructure) 包含链表中所有满足条件的PCI结构体的不可变引用的容器
|
||||
|
||||
/// # get_pci_device_structure - 在链表中寻找满足条件的PCI设备结构体并返回其不可变引用
|
||||
///
|
||||
/// 该函数遍历给定的PCI设备链表,寻找其common_header中class_code和subclass字段与给定值匹配的设备结构体。
|
||||
/// 对于每一个匹配的设备结构体,函数返回一个可变引用。
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>> — 链表的写锁守卫,用于访问和遍历PCI设备链表。
|
||||
/// - class_code: u8 — PCI设备class code寄存器值,用于分类设备的功能。
|
||||
/// - subclass: u8 — PCI设备subclass寄存器值,与class_code一起确定设备的子类型。
|
||||
///
|
||||
/// ## 返回值
|
||||
/// - 包含链表中所有满足条件的PCI结构体的不可变引用的容器。
|
||||
#[allow(clippy::borrowed_box)]
|
||||
pub fn get_pci_device_structure<'a>(
|
||||
list: &'a mut RwLockReadGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
||||
|
@ -94,6 +94,10 @@ impl Serial8250Manager {
|
||||
// todo: 把驱动注册到uart层、tty层
|
||||
uart_manager().register_driver(&(serial8250_isa_driver.clone() as Arc<dyn UartDriver>))?;
|
||||
|
||||
// 把驱动注册到platform总线
|
||||
platform_driver_manager()
|
||||
.register(serial8250_isa_driver.clone() as Arc<dyn PlatformDriver>)?;
|
||||
|
||||
// 注册isa设备到platform总线
|
||||
platform_device_manager()
|
||||
.device_add(serial8250_isa_dev.clone() as Arc<dyn PlatformDevice>)
|
||||
@ -104,10 +108,6 @@ impl Serial8250Manager {
|
||||
return e;
|
||||
})?;
|
||||
|
||||
// 把驱动注册到platform总线
|
||||
platform_driver_manager()
|
||||
.register(serial8250_isa_driver.clone() as Arc<dyn PlatformDriver>)?;
|
||||
|
||||
unsafe {
|
||||
INITIALIZED = true;
|
||||
}
|
||||
|
3
kernel/src/driver/virtio/mmio.rs
Normal file
3
kernel/src/driver/virtio/mmio.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub(super) fn virtio_probe_mmio() {
|
||||
// todo: implement virtio_probe_mmio
|
||||
}
|
@ -1,20 +1,44 @@
|
||||
use core::any::Any;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use alloc::{string::String, sync::Arc};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::exception::{irqdesc::IrqReturn, IrqNumber};
|
||||
|
||||
use super::base::device::DeviceId;
|
||||
use super::base::device::{driver::Driver, Device, DeviceId};
|
||||
|
||||
pub(super) mod irq;
|
||||
pub mod mmio;
|
||||
pub mod sysfs;
|
||||
pub mod transport;
|
||||
pub mod transport_pci;
|
||||
#[allow(clippy::module_inception)]
|
||||
pub mod virtio;
|
||||
pub mod virtio_impl;
|
||||
|
||||
pub trait VirtIODevice: Send + Sync + Any {
|
||||
/// virtio 设备厂商ID
|
||||
pub const VIRTIO_VENDOR_ID: u16 = 0x1af4;
|
||||
|
||||
pub trait VirtIODevice: Device {
|
||||
fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError>;
|
||||
|
||||
fn dev_id(&self) -> &Arc<DeviceId>;
|
||||
|
||||
fn set_device_name(&self, name: String);
|
||||
|
||||
fn device_name(&self) -> String;
|
||||
|
||||
fn set_virtio_device_index(&self, index: VirtIODeviceIndex);
|
||||
|
||||
fn virtio_device_index(&self) -> Option<VirtIODeviceIndex>;
|
||||
|
||||
/// virtio 设备类型
|
||||
fn device_type_id(&self) -> u32;
|
||||
|
||||
/// virtio 设备厂商
|
||||
fn vendor(&self) -> u32;
|
||||
}
|
||||
|
||||
pub trait VirtIODriver: Driver {
|
||||
fn probe(&self, device: &Arc<dyn VirtIODevice>) -> Result<(), SystemError>;
|
||||
}
|
||||
|
||||
int_like!(VirtIODeviceIndex, usize);
|
||||
|
295
kernel/src/driver/virtio/sysfs.rs
Normal file
295
kernel/src/driver/virtio/sysfs.rs
Normal file
@ -0,0 +1,295 @@
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use ida::IdAllocator;
|
||||
use intertrait::cast::CastArc;
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
use crate::{
|
||||
driver::base::{
|
||||
device::{
|
||||
bus::{bus_manager, Bus},
|
||||
device_manager,
|
||||
driver::{driver_manager, Driver},
|
||||
Device,
|
||||
},
|
||||
kobject::KObject,
|
||||
subsys::SubSysPrivate,
|
||||
},
|
||||
filesystem::{
|
||||
sysfs::{
|
||||
file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport, SYSFS_ATTR_MODE_RO,
|
||||
},
|
||||
vfs::syscall::ModeType,
|
||||
},
|
||||
init::initcall::INITCALL_CORE,
|
||||
};
|
||||
|
||||
use super::{VirtIODevice, VirtIODeviceIndex, VirtIODriver};
|
||||
|
||||
static mut VIRTIO_BUS: Option<Arc<VirtIOBus>> = None;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn virtio_bus() -> Arc<VirtIOBus> {
|
||||
unsafe { VIRTIO_BUS.as_ref().unwrap().clone() }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VirtIOBus {
|
||||
private: SubSysPrivate,
|
||||
}
|
||||
|
||||
impl VirtIOBus {
|
||||
pub fn new() -> Arc<Self> {
|
||||
let w: Weak<Self> = Weak::new();
|
||||
let private = SubSysPrivate::new("virtio".to_string(), Some(w), None, &[]);
|
||||
let bus = Arc::new(Self { private });
|
||||
bus.subsystem()
|
||||
.set_bus(Some(Arc::downgrade(&(bus.clone() as Arc<dyn Bus>))));
|
||||
|
||||
return bus;
|
||||
}
|
||||
}
|
||||
|
||||
impl Bus for VirtIOBus {
|
||||
fn name(&self) -> String {
|
||||
self.private.name()
|
||||
}
|
||||
|
||||
fn dev_name(&self) -> String {
|
||||
return self.name();
|
||||
}
|
||||
|
||||
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||
// todo: VirtIODeviceAttrGroup
|
||||
return &[];
|
||||
}
|
||||
|
||||
fn subsystem(&self) -> &SubSysPrivate {
|
||||
return &self.private;
|
||||
}
|
||||
|
||||
fn probe(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let drv = device.driver().ok_or(SystemError::EINVAL)?;
|
||||
let virtio_drv = drv.cast::<dyn VirtIODriver>().map_err(|_| {
|
||||
kerror!(
|
||||
"VirtIOBus::probe() failed: device.driver() is not a VirtioDriver. Device: '{:?}'",
|
||||
device.name()
|
||||
);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
|
||||
let virtio_dev = device.clone().cast::<dyn VirtIODevice>().map_err(|_| {
|
||||
kerror!(
|
||||
"VirtIOBus::probe() failed: device is not a VirtIODevice. Device: '{:?}'",
|
||||
device.name()
|
||||
);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
|
||||
return virtio_drv.probe(&virtio_dev);
|
||||
}
|
||||
|
||||
fn remove(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn sync_state(&self, _device: &Arc<dyn Device>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn shutdown(&self, _device: &Arc<dyn Device>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn resume(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn match_device(
|
||||
&self,
|
||||
_device: &Arc<dyn Device>,
|
||||
_driver: &Arc<dyn Driver>,
|
||||
) -> Result<bool, SystemError> {
|
||||
// todo: https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/virtio/virtio.c#85
|
||||
todo!("VirtIOBus::match_device() is not implemented")
|
||||
}
|
||||
}
|
||||
|
||||
#[unified_init(INITCALL_CORE)]
|
||||
fn virtio_init() -> Result<(), SystemError> {
|
||||
let bus = VirtIOBus::new();
|
||||
unsafe {
|
||||
VIRTIO_BUS = Some(bus.clone());
|
||||
}
|
||||
bus_manager()
|
||||
.register(bus)
|
||||
.expect("Failed to register virtio bus!");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn virtio_driver_manager() -> &'static VirtIODriverManager {
|
||||
&VirtIODriverManager
|
||||
}
|
||||
|
||||
pub struct VirtIODriverManager;
|
||||
|
||||
impl VirtIODriverManager {
|
||||
pub fn register(&self, driver: Arc<dyn VirtIODriver>) -> Result<(), SystemError> {
|
||||
driver.set_bus(Some(Arc::downgrade(&(virtio_bus() as Arc<dyn Bus>))));
|
||||
return driver_manager().register(driver as Arc<dyn Driver>);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn unregister(&self, driver: &Arc<dyn VirtIODriver>) {
|
||||
driver_manager().unregister(&(driver.clone() as Arc<dyn Driver>));
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn virtio_device_manager() -> &'static VirtIODeviceManager {
|
||||
&VirtIODeviceManager
|
||||
}
|
||||
|
||||
pub struct VirtIODeviceManager;
|
||||
|
||||
impl VirtIODeviceManager {
|
||||
pub fn device_add(&self, dev: Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
|
||||
dev.set_bus(Some(Arc::downgrade(&(virtio_bus() as Arc<dyn Bus>))));
|
||||
device_manager().device_default_initialize(&(dev.clone() as Arc<dyn Device>));
|
||||
let drv = dev.driver().ok_or(SystemError::EINVAL)?;
|
||||
|
||||
let virtio_drv = drv.cast::<dyn VirtIODriver>().map_err(|_| {
|
||||
kerror!(
|
||||
"VirtIODeviceManager::device_add() failed: device.driver() is not a VirtioDriver. Device: '{:?}'",
|
||||
dev.name()
|
||||
);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
let virtio_index = VIRTIO_DEVICE_INDEX_MANAGER.alloc();
|
||||
dev.set_virtio_device_index(virtio_index);
|
||||
dev.set_device_name(format!("virtio{}", virtio_index.data()));
|
||||
virtio_drv.probe(&dev)?;
|
||||
|
||||
device_manager().add_device(dev.clone() as Arc<dyn Device>)?;
|
||||
device_manager().add_groups(&(dev as Arc<dyn Device>), &[&VirtIODeviceAttrGroup])
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn device_remove(&self, dev: &Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
|
||||
device_manager().remove(&(dev.clone() as Arc<dyn Device>));
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
static VIRTIO_DEVICE_INDEX_MANAGER: VirtIODeviceIndexManager = VirtIODeviceIndexManager::new();
|
||||
|
||||
/// VirtIO设备索引管理器
|
||||
///
|
||||
/// VirtIO设备索引管理器用于分配和管理VirtIO设备的唯一索引。
|
||||
pub struct VirtIODeviceIndexManager {
|
||||
// ID分配器
|
||||
///
|
||||
/// ID分配器用于分配唯一的索引给VirtIO设备。
|
||||
ida: IdAllocator,
|
||||
}
|
||||
|
||||
// VirtIO设备索引管理器的新建实例
|
||||
impl VirtIODeviceIndexManager {
|
||||
/// 创建新的VirtIO设备索引管理器实例
|
||||
///
|
||||
/// 创建一个新的VirtIO设备索引管理器实例,初始时分配器从0开始,直到最大usize值。
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
ida: IdAllocator::new(0, usize::MAX),
|
||||
}
|
||||
}
|
||||
|
||||
/// 分配一个新的VirtIO设备索引
|
||||
///
|
||||
/// 分配一个唯一的索引给VirtIO设备。
|
||||
pub fn alloc(&self) -> VirtIODeviceIndex {
|
||||
VirtIODeviceIndex(self.ida.alloc().unwrap())
|
||||
}
|
||||
|
||||
// 释放一个VirtIO设备索引
|
||||
///
|
||||
/// 释放之前分配的VirtIO设备索引,使其可以被重新使用。
|
||||
#[allow(dead_code)]
|
||||
pub fn free(&self, index: VirtIODeviceIndex) {
|
||||
self.ida.free(index.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// VirtIO设备属性组
|
||||
///
|
||||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/virtio/virtio.c#64
|
||||
#[derive(Debug)]
|
||||
pub struct VirtIODeviceAttrGroup;
|
||||
|
||||
impl AttributeGroup for VirtIODeviceAttrGroup {
|
||||
fn name(&self) -> Option<&str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn attrs(&self) -> &[&'static dyn Attribute] {
|
||||
&[&AttrDevice, &AttrVendor]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AttrDevice;
|
||||
|
||||
impl Attribute for AttrDevice {
|
||||
fn name(&self) -> &str {
|
||||
"device"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
SYSFS_ATTR_MODE_RO
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::ATTR_SHOW
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let dev = kobj.cast::<dyn VirtIODevice>().map_err(|_| {
|
||||
kerror!("AttrDevice::show() failed: kobj is not a VirtIODevice");
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
let device_type_id = dev.device_type_id();
|
||||
|
||||
return sysfs_emit_str(buf, &format!("0x{:04x}\n", device_type_id));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AttrVendor;
|
||||
|
||||
impl Attribute for AttrVendor {
|
||||
fn name(&self) -> &str {
|
||||
"vendor"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
SYSFS_ATTR_MODE_RO
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::ATTR_SHOW
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let dev = kobj.cast::<dyn VirtIODevice>().map_err(|_| {
|
||||
kerror!("AttrVendor::show() failed: kobj is not a VirtIODevice");
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
let vendor = dev.vendor();
|
||||
|
||||
return sysfs_emit_str(buf, &format!("0x{:04x}\n", vendor));
|
||||
}
|
||||
}
|
131
kernel/src/driver/virtio/transport.rs
Normal file
131
kernel/src/driver/virtio/transport.rs
Normal file
@ -0,0 +1,131 @@
|
||||
use virtio_drivers::transport::Transport;
|
||||
|
||||
use super::transport_pci::PciTransport;
|
||||
|
||||
pub enum VirtIOTransport {
|
||||
Pci(PciTransport),
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for VirtIOTransport {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
VirtIOTransport::Pci(_) => write!(f, "VirtIOTransport::Pci"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Transport for VirtIOTransport {
|
||||
#[inline(always)]
|
||||
fn finish_init(&mut self) {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.finish_init(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn device_type(&self) -> virtio_drivers::transport::DeviceType {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.device_type(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn read_device_features(&mut self) -> u64 {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.read_device_features(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn write_driver_features(&mut self, driver_features: u64) {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.write_driver_features(driver_features),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn max_queue_size(&mut self, queue: u16) -> u32 {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.max_queue_size(queue),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn notify(&mut self, queue: u16) {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.notify(queue),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_status(&self) -> virtio_drivers::transport::DeviceStatus {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.get_status(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_status(&mut self, status: virtio_drivers::transport::DeviceStatus) {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.set_status(status),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_guest_page_size(&mut self, guest_page_size: u32) {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.set_guest_page_size(guest_page_size),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn requires_legacy_layout(&self) -> bool {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.requires_legacy_layout(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn queue_set(
|
||||
&mut self,
|
||||
queue: u16,
|
||||
size: u32,
|
||||
descriptors: virtio_drivers::PhysAddr,
|
||||
driver_area: virtio_drivers::PhysAddr,
|
||||
device_area: virtio_drivers::PhysAddr,
|
||||
) {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => {
|
||||
transport.queue_set(queue, size, descriptors, driver_area, device_area)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn queue_unset(&mut self, queue: u16) {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.queue_unset(queue),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn queue_used(&mut self, queue: u16) -> bool {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.queue_used(queue),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn ack_interrupt(&mut self) -> bool {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.ack_interrupt(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn config_space<T: 'static>(&self) -> virtio_drivers::Result<core::ptr::NonNull<T>> {
|
||||
match self {
|
||||
VirtIOTransport::Pci(transport) => transport.config_space(),
|
||||
}
|
||||
}
|
||||
}
|
@ -32,9 +32,7 @@ use virtio_drivers::{
|
||||
Error, Hal, PhysAddr,
|
||||
};
|
||||
|
||||
/// The PCI vendor ID for VirtIO devices.
|
||||
/// PCI Virtio设备的vendor ID
|
||||
const VIRTIO_VENDOR_ID: u16 = 0x1af4;
|
||||
use super::VIRTIO_VENDOR_ID;
|
||||
|
||||
/// The offset to add to a VirtIO device ID to get the corresponding PCI device ID.
|
||||
/// PCI Virtio设备的DEVICE_ID 的offset
|
||||
|
@ -1,53 +1,51 @@
|
||||
use super::mmio::virtio_probe_mmio;
|
||||
use super::transport_pci::PciTransport;
|
||||
use super::virtio_impl::HalImpl;
|
||||
use crate::driver::base::device::DeviceId;
|
||||
use crate::driver::net::virtio_net::virtio_net;
|
||||
use crate::driver::pci::pci::{
|
||||
get_pci_device_structure_mut, PciDeviceStructure, PciDeviceStructureGeneralDevice,
|
||||
PCI_DEVICE_LINKEDLIST,
|
||||
get_pci_device_structures_mut_by_vendor_id, PciDeviceStructure,
|
||||
PciDeviceStructureGeneralDevice, PCI_DEVICE_LINKEDLIST,
|
||||
};
|
||||
use crate::driver::virtio::transport::VirtIOTransport;
|
||||
use crate::libs::rwlock::RwLockWriteGuard;
|
||||
use crate::{kdebug, kerror, kwarn};
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{boxed::Box, collections::LinkedList};
|
||||
use virtio_drivers::transport::{DeviceType, Transport};
|
||||
const NETWORK_CLASS: u8 = 0x2;
|
||||
const ETHERNET_SUBCLASS: u8 = 0x0;
|
||||
|
||||
//Virtio设备寻找过程中出现的问题
|
||||
enum VirtioError {
|
||||
VirtioNetNotFound,
|
||||
NetDeviceNotFound,
|
||||
}
|
||||
|
||||
///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
|
||||
pub fn virtio_probe() {
|
||||
virtio_probe_pci();
|
||||
virtio_probe_mmio();
|
||||
}
|
||||
|
||||
fn virtio_probe_pci() {
|
||||
let mut list = PCI_DEVICE_LINKEDLIST.write();
|
||||
if let Ok(virtio_list) = virtio_device_search(&mut list) {
|
||||
for virtio_device in virtio_list {
|
||||
let dev_id = virtio_device.common_header.device_id;
|
||||
let dev_id = DeviceId::new(None, Some(format!("virtio_{}", dev_id))).unwrap();
|
||||
match PciTransport::new::<HalImpl>(virtio_device, dev_id.clone()) {
|
||||
Ok(mut transport) => {
|
||||
kdebug!(
|
||||
"Detected virtio PCI device with device type {:?}, features {:#018x}",
|
||||
transport.device_type(),
|
||||
transport.read_device_features(),
|
||||
);
|
||||
virtio_device_init(transport, dev_id);
|
||||
}
|
||||
Err(err) => {
|
||||
kerror!("Pci transport create failed because of error: {}", err);
|
||||
}
|
||||
let virtio_list = virtio_device_search(&mut list);
|
||||
for virtio_device in virtio_list {
|
||||
let dev_id = virtio_device.common_header.device_id;
|
||||
let dev_id = DeviceId::new(None, Some(format!("{dev_id}"))).unwrap();
|
||||
match PciTransport::new::<HalImpl>(virtio_device, dev_id.clone()) {
|
||||
Ok(mut transport) => {
|
||||
kdebug!(
|
||||
"Detected virtio PCI device with device type {:?}, features {:#018x}",
|
||||
transport.device_type(),
|
||||
transport.read_device_features(),
|
||||
);
|
||||
let transport = VirtIOTransport::Pci(transport);
|
||||
virtio_device_init(transport, dev_id);
|
||||
}
|
||||
Err(err) => {
|
||||
kerror!("Pci transport create failed because of error: {}", err);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
kerror!("Error occured when finding virtio device!");
|
||||
}
|
||||
}
|
||||
|
||||
///@brief 为virtio设备寻找对应的驱动进行初始化
|
||||
fn virtio_device_init(transport: impl Transport + 'static, dev_id: Arc<DeviceId>) {
|
||||
fn virtio_device_init(transport: VirtIOTransport, dev_id: Arc<DeviceId>) {
|
||||
match transport.device_type() {
|
||||
DeviceType::Block => {
|
||||
kwarn!("Not support virtio_block device for now");
|
||||
@ -65,39 +63,30 @@ fn virtio_device_init(transport: impl Transport + 'static, dev_id: Arc<DeviceId>
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 寻找所有的virtio设备
|
||||
/// @param list 链表的写锁
|
||||
/// @return Result<LinkedList<&'a mut Pci_Device_Structure_General_Device>, VirtioError> 成功则返回包含所有virtio设备结构体的可变引用的链表,失败则返回err
|
||||
/// 该函数主要是为其他virtio设备预留支持
|
||||
/// # virtio_device_search - 在给定的PCI设备列表中搜索符合特定标准的virtio设备
|
||||
///
|
||||
/// 该函数搜索一个PCI设备列表,找到所有由特定厂商ID(0x1AF4)和设备ID范围(0x1000至0x103F)定义的virtio设备。
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>> - 一个可写的PCI设备结构列表的互斥锁。
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// 返回一个包含所有找到的virtio设备的数组
|
||||
fn virtio_device_search<'a>(
|
||||
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
||||
) -> Result<LinkedList<&'a mut PciDeviceStructureGeneralDevice>, VirtioError> {
|
||||
let mut virtio_list: LinkedList<&mut PciDeviceStructureGeneralDevice> = LinkedList::new();
|
||||
let virtio_net_device = get_virtio_net_device(list)?;
|
||||
virtio_list.push_back(virtio_net_device);
|
||||
Ok(virtio_list)
|
||||
}
|
||||
) -> Vec<&'a mut PciDeviceStructureGeneralDevice> {
|
||||
let mut virtio_list = Vec::new();
|
||||
let result = get_pci_device_structures_mut_by_vendor_id(list, 0x1AF4);
|
||||
|
||||
/// @brief 寻找virtio-net设备
|
||||
/// @param list 链表的写锁
|
||||
/// @return Result<&'a mut Pci_Device_Structure_General_Device, VirtioError> 成功则返回virtio设备结构体的可变引用,失败则返回err
|
||||
fn get_virtio_net_device<'a>(
|
||||
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
||||
) -> Result<&'a mut PciDeviceStructureGeneralDevice, VirtioError> {
|
||||
let result = get_pci_device_structure_mut(list, NETWORK_CLASS, ETHERNET_SUBCLASS);
|
||||
if result.is_empty() {
|
||||
return Err(VirtioError::NetDeviceNotFound);
|
||||
}
|
||||
for device in result {
|
||||
let standard_device = device.as_standard_device_mut().unwrap();
|
||||
let header = &standard_device.common_header;
|
||||
if header.vendor_id == 0x1AF4
|
||||
&& header.device_id >= 0x1000
|
||||
&& header.device_id <= 0x103F
|
||||
&& standard_device.subsystem_id == 1
|
||||
{
|
||||
return Ok(standard_device);
|
||||
if header.device_id >= 0x1000 && header.device_id <= 0x103F {
|
||||
virtio_list.push(standard_device);
|
||||
}
|
||||
}
|
||||
Err(VirtioError::VirtioNetNotFound)
|
||||
|
||||
return virtio_list;
|
||||
}
|
||||
|
@ -107,7 +107,13 @@ pub trait AttributeGroup: Debug + Send + Sync {
|
||||
///
|
||||
/// 如果返回Some,则使用返回的权限。
|
||||
/// 如果要标识属性不可见,则返回Some(ModeType::empty())
|
||||
fn is_visible(&self, kobj: Arc<dyn KObject>, attr: &'static dyn Attribute) -> Option<ModeType>;
|
||||
fn is_visible(
|
||||
&self,
|
||||
_kobj: Arc<dyn KObject>,
|
||||
attr: &'static dyn Attribute,
|
||||
) -> Option<ModeType> {
|
||||
return Some(attr.mode());
|
||||
}
|
||||
}
|
||||
|
||||
/// sysfs只读属性文件的权限
|
||||
|
@ -5,7 +5,7 @@ use core::{
|
||||
|
||||
use alloc::{collections::BTreeMap, sync::Arc};
|
||||
|
||||
use crate::{driver::net::NetDriver, libs::rwlock::RwLock};
|
||||
use crate::{driver::net::NetDevice, libs::rwlock::RwLock};
|
||||
use smoltcp::wire::IpEndpoint;
|
||||
|
||||
use self::socket::SocketInode;
|
||||
@ -18,7 +18,7 @@ pub mod syscall;
|
||||
lazy_static! {
|
||||
/// # 所有网络接口的列表
|
||||
/// 这个列表在中断上下文会使用到,因此需要irqsave
|
||||
pub static ref NET_DRIVERS: RwLock<BTreeMap<usize, Arc<dyn NetDriver>>> = RwLock::new(BTreeMap::new());
|
||||
pub static ref NET_DEVICES: RwLock<BTreeMap<usize, Arc<dyn NetDevice>>> = RwLock::new(BTreeMap::new());
|
||||
}
|
||||
|
||||
/// 生成网络接口的id (全局自增)
|
||||
|
@ -3,10 +3,10 @@ use smoltcp::{socket::dhcpv4, wire};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::net::NetDriver,
|
||||
driver::net::NetDevice,
|
||||
kdebug, kinfo, kwarn,
|
||||
libs::rwlock::RwLockReadGuard,
|
||||
net::{socket::SocketPollMethod, NET_DRIVERS},
|
||||
net::{socket::SocketPollMethod, NET_DEVICES},
|
||||
time::timer::{next_n_ms_timer_jiffies, Timer, TimerFunction},
|
||||
};
|
||||
|
||||
@ -41,7 +41,7 @@ pub fn net_init() -> Result<(), SystemError> {
|
||||
}
|
||||
|
||||
fn dhcp_query() -> Result<(), SystemError> {
|
||||
let binding = NET_DRIVERS.write_irqsave();
|
||||
let binding = NET_DEVICES.write_irqsave();
|
||||
|
||||
let net_face = binding.get(&0).ok_or(SystemError::ENODEV)?.clone();
|
||||
|
||||
@ -119,7 +119,7 @@ fn dhcp_query() -> Result<(), SystemError> {
|
||||
}
|
||||
|
||||
pub fn poll_ifaces() {
|
||||
let guard: RwLockReadGuard<BTreeMap<usize, Arc<dyn NetDriver>>> = NET_DRIVERS.read_irqsave();
|
||||
let guard: RwLockReadGuard<BTreeMap<usize, Arc<dyn NetDevice>>> = NET_DEVICES.read_irqsave();
|
||||
if guard.len() == 0 {
|
||||
kwarn!("poll_ifaces: No net driver found!");
|
||||
return;
|
||||
@ -139,8 +139,8 @@ pub fn poll_ifaces() {
|
||||
pub fn poll_ifaces_try_lock(times: u16) -> Result<(), SystemError> {
|
||||
let mut i = 0;
|
||||
while i < times {
|
||||
let guard: RwLockReadGuard<BTreeMap<usize, Arc<dyn NetDriver>>> =
|
||||
NET_DRIVERS.read_irqsave();
|
||||
let guard: RwLockReadGuard<BTreeMap<usize, Arc<dyn NetDevice>>> =
|
||||
NET_DEVICES.read_irqsave();
|
||||
if guard.len() == 0 {
|
||||
kwarn!("poll_ifaces: No net driver found!");
|
||||
// 没有网卡,返回错误
|
||||
@ -170,7 +170,7 @@ pub fn poll_ifaces_try_lock(times: u16) -> Result<(), SystemError> {
|
||||
/// @return 加锁超时,返回SystemError::EAGAIN_OR_EWOULDBLOCK
|
||||
/// @return 没有网卡,返回SystemError::ENODEV
|
||||
pub fn poll_ifaces_try_lock_onetime() -> Result<(), SystemError> {
|
||||
let guard: RwLockReadGuard<BTreeMap<usize, Arc<dyn NetDriver>>> = NET_DRIVERS.read_irqsave();
|
||||
let guard: RwLockReadGuard<BTreeMap<usize, Arc<dyn NetDevice>>> = NET_DEVICES.read_irqsave();
|
||||
if guard.len() == 0 {
|
||||
kwarn!("poll_ifaces: No net driver found!");
|
||||
// 没有网卡,返回错误
|
||||
|
@ -7,12 +7,12 @@ use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::rand::rand,
|
||||
driver::net::NetDriver,
|
||||
driver::net::NetDevice,
|
||||
kerror, kwarn,
|
||||
libs::rwlock::RwLock,
|
||||
net::{
|
||||
event_poll::EPollEventType, net_core::poll_ifaces, Endpoint, Protocol, ShutdownType,
|
||||
NET_DRIVERS,
|
||||
NET_DEVICES,
|
||||
},
|
||||
};
|
||||
|
||||
@ -151,7 +151,7 @@ impl Socket for RawSocket {
|
||||
socket_set_guard.get_mut::<raw::Socket>(self.handle.smoltcp_handle().unwrap());
|
||||
|
||||
// 暴力解决方案:只考虑0号网卡。 TODO:考虑多网卡的情况!!!
|
||||
let iface = NET_DRIVERS.read_irqsave().get(&0).unwrap().clone();
|
||||
let iface = NET_DEVICES.read_irqsave().get(&0).unwrap().clone();
|
||||
|
||||
// 构造IP头
|
||||
let ipv4_src_addr: Option<wire::Ipv4Address> =
|
||||
@ -700,7 +700,7 @@ impl Socket for TcpSocket {
|
||||
PORT_MANAGER.bind_port(self.metadata.socket_type, temp_port, self.clone())?;
|
||||
|
||||
// kdebug!("temp_port: {}", temp_port);
|
||||
let iface: Arc<dyn NetDriver> = NET_DRIVERS.write_irqsave().get(&0).unwrap().clone();
|
||||
let iface: Arc<dyn NetDevice> = NET_DEVICES.write_irqsave().get(&0).unwrap().clone();
|
||||
let mut inner_iface = iface.inner_iface().lock();
|
||||
// kdebug!("to connect: {ip:?}");
|
||||
|
||||
|
@ -76,6 +76,7 @@ QEMU_SERIAL="-serial file:../serial_opt.txt"
|
||||
QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none"
|
||||
QEMU_ACCELARATE=""
|
||||
QEMU_ARGUMENT=""
|
||||
QEMU_DEVICES=
|
||||
|
||||
# 如果qemu_accel不为空
|
||||
if [ -n "${qemu_accel}" ]; then
|
||||
@ -86,8 +87,11 @@ if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then
|
||||
QEMU_MACHINE=" -machine q35,memory-backend=${QEMU_MEMORY_BACKEND} "
|
||||
QEMU_CPU_FEATURES+="-cpu IvyBridge,apic,x2apic,+fpu,check,+vmx,${allflags}"
|
||||
QEMU_RTC_CLOCK+=" -rtc clock=host,base=localtime"
|
||||
QEMU_DEVICES_DISK="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 "
|
||||
else
|
||||
QEMU_MACHINE=" -machine virt,memory-backend=${QEMU_MEMORY_BACKEND} -cpu sifive-u54 "
|
||||
QEMU_DEVICES_DISK="-device virtio-blk-device,drive=disk "
|
||||
|
||||
fi
|
||||
|
||||
if [ ${ARCH} == "riscv64" ]; then
|
||||
@ -101,7 +105,8 @@ fi
|
||||
|
||||
# ps: 下面这条使用tap的方式,无法dhcp获取到ip,暂时不知道为什么
|
||||
# QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,netdev=nic0 -netdev tap,id=nic0,model=virtio-net-pci,script=qemu/ifup-nat,downscript=qemu/ifdown-nat -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
|
||||
QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -device virtio-net-pci,vectors=5,netdev=hostnet0,id=net0 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
|
||||
QEMU_DEVICES+="${QEMU_DEVICES_DISK} "
|
||||
QEMU_DEVICES+=" -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -device virtio-net-pci,vectors=5,netdev=hostnet0,id=net0 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
|
||||
# E1000E
|
||||
# QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -net nic,model=e1000e,netdev=hostnet0,id=net0 -netdev user,id=hostnet1,hostfwd=tcp::12581-:12581 -device virtio-net-pci,vectors=5,netdev=hostnet1,id=net1 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
|
||||
QEMU_ARGUMENT+="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d ${QEMU_MONITOR} -d ${qemu_trace_std} "
|
||||
|
Loading…
x
Reference in New Issue
Block a user