mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +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,
|
IA32_X2APIC_VERSION,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{kdebug, kinfo};
|
use crate::kinfo;
|
||||||
|
|
||||||
use super::{hw_irq::ApicId, LVTRegister, LocalAPIC, LVT};
|
use super::{hw_irq::ApicId, LVTRegister, LocalAPIC, LVT};
|
||||||
|
|
||||||
@ -55,9 +55,9 @@ impl LocalAPIC for X2Apic {
|
|||||||
kinfo!("x2APIC EOI broadcast suppression enabled.");
|
kinfo!("x2APIC EOI broadcast suppression enabled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kdebug!("x2apic: to mask all lvt");
|
// kdebug!("x2apic: to mask all lvt");
|
||||||
self.mask_all_lvt();
|
self.mask_all_lvt();
|
||||||
kdebug!("x2apic: all lvt masked");
|
// kdebug!("x2apic: all lvt masked");
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -147,12 +147,12 @@ pub trait Bus: Debug + Send + Sync {
|
|||||||
|
|
||||||
fn resume(&self, device: &Arc<dyn Device>) -> Result<(), SystemError>;
|
fn resume(&self, device: &Arc<dyn Device>) -> Result<(), SystemError>;
|
||||||
|
|
||||||
/// match platform device to platform driver.
|
/// match device to driver.
|
||||||
///
|
///
|
||||||
/// ## 参数
|
/// ## 参数
|
||||||
///
|
///
|
||||||
/// * `device` - platform device
|
/// * `device` - device
|
||||||
/// * `driver` - platform driver
|
/// * `driver` - driver
|
||||||
///
|
///
|
||||||
/// ## 返回
|
/// ## 返回
|
||||||
///
|
///
|
||||||
|
@ -180,7 +180,7 @@ impl DeviceManager {
|
|||||||
///
|
///
|
||||||
/// 如果传递的设备已成功完成对驱动程序的探测,则返回true,否则返回false。
|
/// 如果传递的设备已成功完成对驱动程序的探测,则返回true,否则返回false。
|
||||||
pub fn device_is_bound(&self, dev: &Arc<dyn Device>) -> bool {
|
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> {
|
pub fn device_bind_driver(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
let r = driver_manager().driver_sysfs_add(dev);
|
let r = driver_manager().driver_sysfs_add(dev);
|
||||||
if let Err(e) = r {
|
if let Err(e) = r {
|
||||||
|
kerror!(
|
||||||
|
"device_bind_driver: driver_sysfs_add failed, dev: '{}', err: {:?}",
|
||||||
|
dev.name(),
|
||||||
|
e
|
||||||
|
);
|
||||||
self.device_links_force_bind(dev);
|
self.device_links_force_bind(dev);
|
||||||
driver_manager().driver_bound(dev);
|
driver_manager().driver_bound(dev);
|
||||||
return Err(e);
|
return Err(e);
|
||||||
@ -606,7 +611,7 @@ impl Attribute for DeviceAttrStateSynced {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct DeviceAttrCoredump;
|
pub(super) struct DeviceAttrCoredump;
|
||||||
|
|
||||||
impl Attribute for DeviceAttrCoredump {
|
impl Attribute for DeviceAttrCoredump {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
|
@ -3,10 +3,14 @@ use super::{
|
|||||||
Device, DeviceMatchName, DeviceMatcher, IdTable,
|
Device, DeviceMatchName, DeviceMatcher, IdTable,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::base::kobject::KObject,
|
driver::base::{
|
||||||
|
device::{bus::BusNotifyEvent, dd::DeviceAttrCoredump, device_manager},
|
||||||
|
kobject::KObject,
|
||||||
|
},
|
||||||
filesystem::sysfs::{sysfs_instance, Attribute, AttributeGroup},
|
filesystem::sysfs::{sysfs_instance, Attribute, AttributeGroup},
|
||||||
};
|
};
|
||||||
use alloc::{
|
use alloc::{
|
||||||
|
string::ToString,
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
@ -226,8 +230,38 @@ impl DriverManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#434
|
/// 参考: 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> {
|
pub fn driver_sysfs_add(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||||
todo!("DriverManager::driver_sysfs_add()");
|
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(
|
pub fn add_groups(
|
||||||
|
@ -22,6 +22,7 @@ use super::{
|
|||||||
driver::Driver,
|
driver::Driver,
|
||||||
Device,
|
Device,
|
||||||
},
|
},
|
||||||
|
kobject::KObject,
|
||||||
kset::KSet,
|
kset::KSet,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -82,6 +83,10 @@ impl SubSysPrivate {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> String {
|
||||||
|
return self.subsys.name();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn subsys(&self) -> Arc<KSet> {
|
pub fn subsys(&self) -> Arc<KSet> {
|
||||||
return self.subsys.clone();
|
return self.subsys.clone();
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,15 @@ use crate::{
|
|||||||
arch::rand::rand,
|
arch::rand::rand,
|
||||||
driver::{
|
driver::{
|
||||||
base::{
|
base::{
|
||||||
device::{bus::Bus, driver::Driver, Device, IdTable},
|
class::Class,
|
||||||
|
device::{bus::Bus, driver::Driver, Device, DeviceType, IdTable},
|
||||||
kobject::{KObjType, KObject, KObjectState},
|
kobject::{KObjType, KObject, KObjectState},
|
||||||
},
|
},
|
||||||
net::NetDriver,
|
net::NetDevice,
|
||||||
},
|
},
|
||||||
kinfo,
|
kinfo,
|
||||||
libs::spinlock::SpinLock,
|
libs::spinlock::SpinLock,
|
||||||
net::{generate_iface_id, NET_DRIVERS},
|
net::{generate_iface_id, NET_DEVICES},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
use alloc::{
|
use alloc::{
|
||||||
@ -205,33 +206,49 @@ impl Debug for E1000EInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Driver for E1000EInterface {
|
impl Device for E1000EInterface {
|
||||||
fn id_table(&self) -> Option<IdTable> {
|
fn dev_type(&self) -> DeviceType {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_device(&self, _device: Arc<dyn Device>) {
|
fn id_table(&self) -> IdTable {
|
||||||
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!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
|
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
|
||||||
todo!()
|
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 {
|
fn mac(&self) -> smoltcp::wire::EthernetAddress {
|
||||||
let mac = self.driver.inner.lock().mac_address();
|
let mac = self.driver.inner.lock().mac_address();
|
||||||
return smoltcp::wire::EthernetAddress::from_bytes(&mac);
|
return smoltcp::wire::EthernetAddress::from_bytes(&mac);
|
||||||
@ -347,7 +364,7 @@ pub fn e1000e_driver_init(device: E1000EDevice) {
|
|||||||
let driver = E1000EDriver::new(device);
|
let driver = E1000EDriver::new(device);
|
||||||
let iface = E1000EInterface::new(driver);
|
let iface = E1000EInterface::new(driver);
|
||||||
// 将网卡的接口信息注册到全局的网卡接口信息表中
|
// 将网卡的接口信息注册到全局的网卡接口信息表中
|
||||||
NET_DRIVERS
|
NET_DEVICES
|
||||||
.write_irqsave()
|
.write_irqsave()
|
||||||
.insert(iface.nic_id(), iface.clone());
|
.insert(iface.nic_id(), iface.clone());
|
||||||
kinfo!("e1000e driver init successfully!\tMAC: [{}]", mac);
|
kinfo!("e1000e driver init successfully!\tMAC: [{}]", mac);
|
||||||
|
@ -4,7 +4,7 @@ use smoltcp::{
|
|||||||
wire::{self, EthernetAddress},
|
wire::{self, EthernetAddress},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::base::device::driver::Driver;
|
use super::base::device::Device;
|
||||||
use crate::libs::spinlock::SpinLock;
|
use crate::libs::spinlock::SpinLock;
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ pub mod e1000e;
|
|||||||
pub mod irq_handle;
|
pub mod irq_handle;
|
||||||
pub mod virtio_net;
|
pub mod virtio_net;
|
||||||
|
|
||||||
pub trait NetDriver: Driver {
|
pub trait NetDevice: Device {
|
||||||
/// @brief 获取网卡的MAC地址
|
/// @brief 获取网卡的MAC地址
|
||||||
fn mac(&self) -> EthernetAddress;
|
fn mac(&self) -> EthernetAddress;
|
||||||
|
|
||||||
|
@ -1,123 +1,206 @@
|
|||||||
use core::{
|
use core::{
|
||||||
|
any::Any,
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloc::{
|
use alloc::{
|
||||||
string::String,
|
string::{String, ToString},
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use smoltcp::{iface, phy, wire};
|
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::{
|
use crate::{
|
||||||
arch::rand::rand,
|
arch::rand::rand,
|
||||||
driver::{
|
driver::{
|
||||||
base::{
|
base::{
|
||||||
device::{bus::Bus, driver::Driver, Device, DeviceId, IdTable},
|
class::Class,
|
||||||
kobject::{KObjType, KObject, KObjectState},
|
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},
|
exception::{irqdesc::IrqReturn, IrqNumber},
|
||||||
kerror, kinfo,
|
filesystem::kernfs::KernFSInode,
|
||||||
libs::spinlock::SpinLock,
|
init::initcall::INITCALL_POSTCORE,
|
||||||
net::{generate_iface_id, net_core::poll_ifaces_try_lock_onetime, NET_DRIVERS},
|
kerror,
|
||||||
|
libs::{
|
||||||
|
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||||
|
spinlock::{SpinLock, SpinLockGuard},
|
||||||
|
},
|
||||||
|
net::{generate_iface_id, net_core::poll_ifaces_try_lock_onetime, NET_DEVICES},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
/// @brief Virtio网络设备驱动(加锁)
|
static mut VIRTIO_NET_DRIVER: Option<Arc<VirtIONetDriver>> = None;
|
||||||
pub struct VirtioNICDriver<T: Transport> {
|
|
||||||
pub inner: Arc<SpinLock<VirtIONet<HalImpl, T, 2>>>,
|
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> {
|
pub struct VirtIoNetImpl {
|
||||||
fn clone(&self) -> Self {
|
inner: VirtIONet<HalImpl, VirtIOTransport, 2>,
|
||||||
return VirtioNICDriver {
|
}
|
||||||
inner: self.inner.clone(),
|
|
||||||
};
|
impl VirtIoNetImpl {
|
||||||
|
const fn new(inner: VirtIONet<HalImpl, VirtIOTransport, 2>) -> Self {
|
||||||
|
Self { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。
|
impl Deref for VirtIoNetImpl {
|
||||||
///
|
type Target = VirtIONet<HalImpl, VirtIOTransport, 2>;
|
||||||
/// 由于smoltcp的设计,导致需要在poll的时候获取网卡驱动的可变引用,
|
fn deref(&self) -> &Self::Target {
|
||||||
/// 同时需要在token的consume里面获取可变引用。为了避免双重加锁,所以需要这个包裹器。
|
&self.inner
|
||||||
struct VirtioNICDriverWrapper<T: Transport>(UnsafeCell<VirtioNICDriver<T>>);
|
}
|
||||||
unsafe impl<T: Transport> Send for VirtioNICDriverWrapper<T> {}
|
}
|
||||||
unsafe impl<T: Transport> Sync for VirtioNICDriverWrapper<T> {}
|
|
||||||
|
|
||||||
impl<T: Transport> Deref for VirtioNICDriverWrapper<T> {
|
impl DerefMut for VirtIoNetImpl {
|
||||||
type Target = VirtioNICDriver<T>;
|
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 {
|
fn deref(&self) -> &Self::Target {
|
||||||
unsafe { &*self.0.get() }
|
unsafe { &*self.0.get() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T: Transport> DerefMut for VirtioNICDriverWrapper<T> {
|
impl DerefMut for VirtIONicDeviceInnerWrapper {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
unsafe { &mut *self.0.get() }
|
unsafe { &mut *self.0.get() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::mut_from_ref)]
|
#[allow(clippy::mut_from_ref)]
|
||||||
impl<T: Transport> VirtioNICDriverWrapper<T> {
|
impl VirtIONicDeviceInnerWrapper {
|
||||||
fn force_get_mut(&self) -> &mut VirtioNICDriver<T> {
|
fn force_get_mut(&self) -> &mut <VirtIONicDeviceInnerWrapper as Deref>::Target {
|
||||||
unsafe { &mut *self.0.get() }
|
unsafe { &mut *self.0.get() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Transport> Debug for VirtioNICDriver<T> {
|
/// Virtio网络设备驱动(加锁)
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
pub struct VirtIONicDeviceInner {
|
||||||
f.debug_struct("VirtioNICDriver").finish()
|
pub inner: Arc<SpinLock<VirtIoNetImpl>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for VirtIONicDeviceInner {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
return VirtIONicDeviceInner {
|
||||||
|
inner: self.inner.clone(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VirtioInterface<T: Transport> {
|
impl Debug for VirtIONicDeviceInner {
|
||||||
driver: VirtioNICDriverWrapper<T>,
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
iface_id: usize,
|
f.debug_struct("VirtIONicDriver").finish()
|
||||||
iface: SpinLock<iface::Interface>,
|
}
|
||||||
name: String,
|
|
||||||
dev_id: Arc<DeviceId>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
f.debug_struct("VirtioInterface")
|
f.debug_struct("VirtioInterface")
|
||||||
.field("driver", self.driver.deref())
|
|
||||||
.field("iface_id", &self.iface_id)
|
.field("iface_id", &self.iface_id)
|
||||||
.field("iface", &"smoltcp::iface::Interface")
|
.field("iface_name", &self.iface_name)
|
||||||
.field("name", &self.name)
|
.field("dev_id", &self.dev_id)
|
||||||
|
.field("inner", &self.inner)
|
||||||
|
.field("locked_kobj_state", &self.locked_kobj_state)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Transport> VirtioInterface<T> {
|
impl VirtioInterface {
|
||||||
pub fn new(mut driver: VirtioNICDriver<T>, dev_id: Arc<DeviceId>) -> Arc<Self> {
|
pub fn new(mut device_inner: VirtIONicDeviceInner, dev_id: Arc<DeviceId>) -> Arc<Self> {
|
||||||
let iface_id = generate_iface_id();
|
let iface_id = generate_iface_id();
|
||||||
let mut iface_config = iface::Config::new(wire::HardwareAddress::Ethernet(
|
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;
|
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 {
|
let result = Arc::new(VirtioInterface {
|
||||||
driver,
|
device_inner: VirtIONicDeviceInnerWrapper(UnsafeCell::new(device_inner)),
|
||||||
iface_id,
|
iface_id,
|
||||||
|
locked_kobj_state: LockedKObjectState::default(),
|
||||||
iface: SpinLock::new(iface),
|
iface: SpinLock::new(iface),
|
||||||
name: format!("eth{}", iface_id),
|
iface_name: format!("eth{}", iface_id),
|
||||||
dev_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;
|
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> {
|
fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError> {
|
||||||
poll_ifaces_try_lock_onetime().ok();
|
poll_ifaces_try_lock_onetime().ok();
|
||||||
return Ok(IrqReturn::Handled);
|
return Ok(IrqReturn::Handled);
|
||||||
@ -126,46 +209,133 @@ impl<T: Transport + 'static> VirtIODevice for VirtioInterface<T> {
|
|||||||
fn dev_id(&self) -> &Arc<DeviceId> {
|
fn dev_id(&self) -> &Arc<DeviceId> {
|
||||||
return &self.dev_id;
|
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 virtio_device_index(&self) -> Option<VirtIODeviceIndex> {
|
||||||
fn drop(&mut self) {
|
return self.inner().virtio_index;
|
||||||
// 从全局的网卡接口信息表中删除这个网卡的接口信息
|
}
|
||||||
NET_DRIVERS.write_irqsave().remove(&self.iface_id);
|
|
||||||
|
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> {
|
impl Drop for VirtioInterface {
|
||||||
pub fn new(driver_net: VirtIONet<HalImpl, T, 2>) -> Self {
|
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(
|
let mut iface_config = iface::Config::new(wire::HardwareAddress::Ethernet(
|
||||||
wire::EthernetAddress(driver_net.mac_address()),
|
wire::EthernetAddress(driver_net.mac_address()),
|
||||||
));
|
));
|
||||||
|
|
||||||
iface_config.random_seed = rand() as u64;
|
iface_config.random_seed = rand() as u64;
|
||||||
|
|
||||||
let inner: Arc<SpinLock<VirtIONet<HalImpl, T, 2>>> = Arc::new(SpinLock::new(driver_net));
|
let inner = Arc::new(SpinLock::new(VirtIoNetImpl::new(driver_net)));
|
||||||
let result = VirtioNICDriver { inner };
|
let result = VirtIONicDeviceInner { inner };
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VirtioNetToken<T: Transport> {
|
pub struct VirtioNetToken {
|
||||||
driver: VirtioNICDriver<T>,
|
driver: VirtIONicDeviceInner,
|
||||||
rx_buffer: Option<virtio_drivers::device::net::RxBuffer>,
|
rx_buffer: Option<virtio_drivers::device::net::RxBuffer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Transport> VirtioNetToken<T> {
|
impl VirtioNetToken {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
driver: VirtioNICDriver<T>,
|
driver: VirtIONicDeviceInner,
|
||||||
rx_buffer: Option<virtio_drivers::device::net::RxBuffer>,
|
rx_buffer: Option<virtio_drivers::device::net::RxBuffer>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
return Self { driver, rx_buffer };
|
return Self { driver, rx_buffer };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Transport> phy::Device for VirtioNICDriver<T> {
|
impl phy::Device for VirtIONicDeviceInner {
|
||||||
type RxToken<'a> = VirtioNetToken<T> where Self: 'a;
|
type RxToken<'a> = VirtioNetToken where Self: 'a;
|
||||||
type TxToken<'a> = VirtioNetToken<T> where Self: 'a;
|
type TxToken<'a> = VirtioNetToken where Self: 'a;
|
||||||
|
|
||||||
fn receive(
|
fn receive(
|
||||||
&mut self,
|
&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
|
fn consume<R, F>(self, len: usize, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut [u8]) -> R,
|
F: FnOnce(&mut [u8]) -> R,
|
||||||
{
|
{
|
||||||
// // 为了线程安全,这里需要对VirtioNet进行加【写锁】,以保证对设备的互斥访问。
|
// // 为了线程安全,这里需要对VirtioNet进行加【写锁】,以保证对设备的互斥访问。
|
||||||
|
|
||||||
let mut driver_net = self.driver.inner.lock();
|
let mut driver_net = self.driver.inner.lock();
|
||||||
let mut tx_buf = driver_net.new_tx_buffer(len);
|
let mut tx_buf = driver_net.new_tx_buffer(len);
|
||||||
let result = f(tx_buf.packet_mut());
|
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
|
fn consume<R, F>(self, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut [u8]) -> R,
|
F: FnOnce(&mut [u8]) -> R,
|
||||||
@ -239,9 +408,9 @@ impl<T: Transport> phy::RxToken for VirtioNetToken<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @brief virtio-net 驱动的初始化与测试
|
/// @brief virtio-net 驱动的初始化与测试
|
||||||
pub fn virtio_net<T: Transport + 'static>(transport: T, dev_id: Arc<DeviceId>) {
|
pub fn virtio_net(transport: VirtIOTransport, dev_id: Arc<DeviceId>) {
|
||||||
let driver_net: VirtIONet<HalImpl, T, 2> =
|
let driver_net: VirtIONet<HalImpl, VirtIOTransport, 2> =
|
||||||
match VirtIONet::<HalImpl, T, 2>::new(transport, 4096) {
|
match VirtIONet::<HalImpl, VirtIOTransport, 2>::new(transport, 4096) {
|
||||||
Ok(net) => net,
|
Ok(net) => net,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
kerror!("VirtIONet init failed");
|
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 mac = wire::EthernetAddress::from_bytes(&driver_net.mac_address());
|
||||||
let driver: VirtioNICDriver<T> = VirtioNICDriver::new(driver_net);
|
let dev_inner = VirtIONicDeviceInner::new(driver_net);
|
||||||
let iface = VirtioInterface::new(driver, dev_id);
|
let iface = VirtioInterface::new(dev_inner, dev_id);
|
||||||
let name = iface.name.clone();
|
kdebug!("To add virtio net: {}, mac: {}", iface.device_name(), mac);
|
||||||
// 将网卡的接口信息注册到全局的网卡接口信息表中
|
virtio_device_manager()
|
||||||
NET_DRIVERS
|
.device_add(iface.clone() as Arc<dyn VirtIODevice>)
|
||||||
.write_irqsave()
|
.expect("Add virtio net failed");
|
||||||
.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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Transport + 'static> Driver for VirtioInterface<T> {
|
impl NetDevice for VirtioInterface {
|
||||||
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> {
|
|
||||||
fn mac(&self) -> wire::EthernetAddress {
|
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);
|
return wire::EthernetAddress::from_bytes(&mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +439,7 @@ impl<T: Transport + 'static> NetDriver for VirtioInterface<T> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> String {
|
||||||
return self.name.clone();
|
return self.iface_name.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_ip_addrs(&self, ip_addrs: &[wire::IpCidr]) -> Result<(), SystemError> {
|
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> {
|
fn poll(&self, sockets: &mut iface::SocketSet) -> Result<(), SystemError> {
|
||||||
let timestamp: smoltcp::time::Instant = Instant::now().into();
|
let timestamp: smoltcp::time::Instant = Instant::now().into();
|
||||||
let mut guard = self.iface.lock();
|
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!!!
|
// todo: notify!!!
|
||||||
// kdebug!("Virtio Interface poll:{poll_res}");
|
// kdebug!("Virtio Interface poll:{poll_res}");
|
||||||
if 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 {
|
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_inode(&self, _inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
|
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
|
||||||
todo!()
|
self.inner().kobj_common.kern_inode = inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
|
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||||
todo!()
|
self.inner().kobj_common.kern_inode.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
|
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||||
todo!()
|
self.inner().kobj_common.parent.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) {
|
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
|
||||||
todo!()
|
self.inner().kobj_common.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
|
fn kset(&self) -> Option<Arc<KSet>> {
|
||||||
todo!()
|
self.inner().kobj_common.kset.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_kset(&self, _kset: Option<Arc<crate::driver::base::kset::KSet>>) {
|
fn set_kset(&self, kset: Option<Arc<KSet>>) {
|
||||||
todo!()
|
self.inner().kobj_common.kset = kset;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
|
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||||
todo!()
|
self.inner().kobj_common.kobj_type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> String {
|
||||||
self.name.clone()
|
self.device_name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_name(&self, _name: String) {
|
fn set_name(&self, _name: String) {
|
||||||
todo!()
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kobj_state(
|
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||||
&self,
|
self.locked_kobj_state.read()
|
||||||
) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kobj_state_mut(
|
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||||
&self,
|
self.locked_kobj_state.write()
|
||||||
) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_kobj_state(&self, _state: KObjectState) {
|
fn set_kobj_state(&self, state: KObjectState) {
|
||||||
todo!()
|
*self.locked_kobj_state.write() = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
|
||||||
todo!()
|
self.inner().kobj_common.kobj_type = ktype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 向编译器保证,VirtioNICDriver在线程之间是安全的.
|
#[unified_init(INITCALL_POSTCORE)]
|
||||||
// 由于smoltcp只会在token内真正操作网卡设备,并且在VirtioNetToken的consume
|
fn virtio_net_driver_init() -> Result<(), SystemError> {
|
||||||
// 方法内,会对VirtioNet进行加【写锁】,因此,能够保证对设备操作的的互斥访问,
|
let driver = VirtIONetDriver::new();
|
||||||
// 因此VirtioNICDriver在线程之间是安全的。
|
virtio_driver_manager()
|
||||||
// unsafe impl<T: Transport> Sync for VirtioNICDriver<T> {}
|
.register(driver.clone() as Arc<dyn VirtIODriver>)
|
||||||
// unsafe impl<T: Transport> Send for VirtioNICDriver<T> {}
|
.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设备结构体并返回其可变引用
|
/// # 获取具有特定供应商ID的PCI设备结构的引用
|
||||||
/// @param list 链表的写锁守卫
|
///
|
||||||
/// @param class_code 寄存器值
|
/// 这个函数通过供应商ID搜索PCI设备结构列表,并返回匹配该ID的所有设备结构的引用。
|
||||||
/// @param subclass 寄存器值,与class_code一起确定设备类型
|
///
|
||||||
/// @return Vec<&'a mut Box<(dyn PciDeviceStructure) 包含链表中所有满足条件的PCI结构体的可变引用的容器
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - 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>(
|
pub fn get_pci_device_structure_mut<'a>(
|
||||||
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
||||||
class_code: u8,
|
class_code: u8,
|
||||||
@ -114,11 +148,20 @@ pub fn get_pci_device_structure_mut<'a>(
|
|||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
/// @brief 在链表中寻找满足条件的PCI设备结构体并返回其不可变引用
|
|
||||||
/// @param list 链表的读锁守卫
|
/// # get_pci_device_structure - 在链表中寻找满足条件的PCI设备结构体并返回其不可变引用
|
||||||
/// @param class_code 寄存器值
|
///
|
||||||
/// @param subclass 寄存器值,与class_code一起确定设备类型
|
/// 该函数遍历给定的PCI设备链表,寻找其common_header中class_code和subclass字段与给定值匹配的设备结构体。
|
||||||
/// @return Vec<&'a Box<(dyn PciDeviceStructure) 包含链表中所有满足条件的PCI结构体的不可变引用的容器
|
/// 对于每一个匹配的设备结构体,函数返回一个可变引用。
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - 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)]
|
#[allow(clippy::borrowed_box)]
|
||||||
pub fn get_pci_device_structure<'a>(
|
pub fn get_pci_device_structure<'a>(
|
||||||
list: &'a mut RwLockReadGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
list: &'a mut RwLockReadGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
||||||
|
@ -94,6 +94,10 @@ impl Serial8250Manager {
|
|||||||
// todo: 把驱动注册到uart层、tty层
|
// todo: 把驱动注册到uart层、tty层
|
||||||
uart_manager().register_driver(&(serial8250_isa_driver.clone() as Arc<dyn UartDriver>))?;
|
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总线
|
// 注册isa设备到platform总线
|
||||||
platform_device_manager()
|
platform_device_manager()
|
||||||
.device_add(serial8250_isa_dev.clone() as Arc<dyn PlatformDevice>)
|
.device_add(serial8250_isa_dev.clone() as Arc<dyn PlatformDevice>)
|
||||||
@ -104,10 +108,6 @@ impl Serial8250Manager {
|
|||||||
return e;
|
return e;
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// 把驱动注册到platform总线
|
|
||||||
platform_driver_manager()
|
|
||||||
.register(serial8250_isa_driver.clone() as Arc<dyn PlatformDriver>)?;
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
INITIALIZED = true;
|
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::{string::String, sync::Arc};
|
||||||
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::exception::{irqdesc::IrqReturn, IrqNumber};
|
use crate::exception::{irqdesc::IrqReturn, IrqNumber};
|
||||||
|
|
||||||
use super::base::device::DeviceId;
|
use super::base::device::{driver::Driver, Device, DeviceId};
|
||||||
|
|
||||||
pub(super) mod irq;
|
pub(super) mod irq;
|
||||||
|
pub mod mmio;
|
||||||
|
pub mod sysfs;
|
||||||
|
pub mod transport;
|
||||||
pub mod transport_pci;
|
pub mod transport_pci;
|
||||||
#[allow(clippy::module_inception)]
|
#[allow(clippy::module_inception)]
|
||||||
pub mod virtio;
|
pub mod virtio;
|
||||||
pub mod virtio_impl;
|
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 handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError>;
|
||||||
|
|
||||||
fn dev_id(&self) -> &Arc<DeviceId>;
|
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,
|
Error, Hal, PhysAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The PCI vendor ID for VirtIO devices.
|
use super::VIRTIO_VENDOR_ID;
|
||||||
/// PCI Virtio设备的vendor ID
|
|
||||||
const VIRTIO_VENDOR_ID: u16 = 0x1af4;
|
|
||||||
|
|
||||||
/// The offset to add to a VirtIO device ID to get the corresponding PCI device ID.
|
/// The offset to add to a VirtIO device ID to get the corresponding PCI device ID.
|
||||||
/// PCI Virtio设备的DEVICE_ID 的offset
|
/// PCI Virtio设备的DEVICE_ID 的offset
|
||||||
|
@ -1,53 +1,51 @@
|
|||||||
|
use super::mmio::virtio_probe_mmio;
|
||||||
use super::transport_pci::PciTransport;
|
use super::transport_pci::PciTransport;
|
||||||
use super::virtio_impl::HalImpl;
|
use super::virtio_impl::HalImpl;
|
||||||
use crate::driver::base::device::DeviceId;
|
use crate::driver::base::device::DeviceId;
|
||||||
use crate::driver::net::virtio_net::virtio_net;
|
use crate::driver::net::virtio_net::virtio_net;
|
||||||
use crate::driver::pci::pci::{
|
use crate::driver::pci::pci::{
|
||||||
get_pci_device_structure_mut, PciDeviceStructure, PciDeviceStructureGeneralDevice,
|
get_pci_device_structures_mut_by_vendor_id, PciDeviceStructure,
|
||||||
PCI_DEVICE_LINKEDLIST,
|
PciDeviceStructureGeneralDevice, PCI_DEVICE_LINKEDLIST,
|
||||||
};
|
};
|
||||||
|
use crate::driver::virtio::transport::VirtIOTransport;
|
||||||
use crate::libs::rwlock::RwLockWriteGuard;
|
use crate::libs::rwlock::RwLockWriteGuard;
|
||||||
use crate::{kdebug, kerror, kwarn};
|
use crate::{kdebug, kerror, kwarn};
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use alloc::{boxed::Box, collections::LinkedList};
|
use alloc::{boxed::Box, collections::LinkedList};
|
||||||
use virtio_drivers::transport::{DeviceType, Transport};
|
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设备也可添加)
|
///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
|
||||||
pub fn virtio_probe() {
|
pub fn virtio_probe() {
|
||||||
|
virtio_probe_pci();
|
||||||
|
virtio_probe_mmio();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn virtio_probe_pci() {
|
||||||
let mut list = PCI_DEVICE_LINKEDLIST.write();
|
let mut list = PCI_DEVICE_LINKEDLIST.write();
|
||||||
if let Ok(virtio_list) = virtio_device_search(&mut list) {
|
let virtio_list = virtio_device_search(&mut list);
|
||||||
for virtio_device in virtio_list {
|
for virtio_device in virtio_list {
|
||||||
let dev_id = virtio_device.common_header.device_id;
|
let dev_id = virtio_device.common_header.device_id;
|
||||||
let dev_id = DeviceId::new(None, Some(format!("virtio_{}", dev_id))).unwrap();
|
let dev_id = DeviceId::new(None, Some(format!("{dev_id}"))).unwrap();
|
||||||
match PciTransport::new::<HalImpl>(virtio_device, dev_id.clone()) {
|
match PciTransport::new::<HalImpl>(virtio_device, dev_id.clone()) {
|
||||||
Ok(mut transport) => {
|
Ok(mut transport) => {
|
||||||
kdebug!(
|
kdebug!(
|
||||||
"Detected virtio PCI device with device type {:?}, features {:#018x}",
|
"Detected virtio PCI device with device type {:?}, features {:#018x}",
|
||||||
transport.device_type(),
|
transport.device_type(),
|
||||||
transport.read_device_features(),
|
transport.read_device_features(),
|
||||||
);
|
);
|
||||||
virtio_device_init(transport, dev_id);
|
let transport = VirtIOTransport::Pci(transport);
|
||||||
}
|
virtio_device_init(transport, dev_id);
|
||||||
Err(err) => {
|
}
|
||||||
kerror!("Pci transport create failed because of error: {}", err);
|
Err(err) => {
|
||||||
}
|
kerror!("Pci transport create failed because of error: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
kerror!("Error occured when finding virtio device!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///@brief 为virtio设备寻找对应的驱动进行初始化
|
///@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() {
|
match transport.device_type() {
|
||||||
DeviceType::Block => {
|
DeviceType::Block => {
|
||||||
kwarn!("Not support virtio_block device for now");
|
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设备
|
/// # virtio_device_search - 在给定的PCI设备列表中搜索符合特定标准的virtio设备
|
||||||
/// @param list 链表的写锁
|
///
|
||||||
/// @return Result<LinkedList<&'a mut Pci_Device_Structure_General_Device>, VirtioError> 成功则返回包含所有virtio设备结构体的可变引用的链表,失败则返回err
|
/// 该函数搜索一个PCI设备列表,找到所有由特定厂商ID(0x1AF4)和设备ID范围(0x1000至0x103F)定义的virtio设备。
|
||||||
/// 该函数主要是为其他virtio设备预留支持
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>> - 一个可写的PCI设备结构列表的互斥锁。
|
||||||
|
///
|
||||||
|
/// ## 返回值
|
||||||
|
///
|
||||||
|
/// 返回一个包含所有找到的virtio设备的数组
|
||||||
fn virtio_device_search<'a>(
|
fn virtio_device_search<'a>(
|
||||||
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
||||||
) -> Result<LinkedList<&'a mut PciDeviceStructureGeneralDevice>, VirtioError> {
|
) -> Vec<&'a mut PciDeviceStructureGeneralDevice> {
|
||||||
let mut virtio_list: LinkedList<&mut PciDeviceStructureGeneralDevice> = LinkedList::new();
|
let mut virtio_list = Vec::new();
|
||||||
let virtio_net_device = get_virtio_net_device(list)?;
|
let result = get_pci_device_structures_mut_by_vendor_id(list, 0x1AF4);
|
||||||
virtio_list.push_back(virtio_net_device);
|
|
||||||
Ok(virtio_list)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @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 {
|
for device in result {
|
||||||
let standard_device = device.as_standard_device_mut().unwrap();
|
let standard_device = device.as_standard_device_mut().unwrap();
|
||||||
let header = &standard_device.common_header;
|
let header = &standard_device.common_header;
|
||||||
if header.vendor_id == 0x1AF4
|
if header.device_id >= 0x1000 && header.device_id <= 0x103F {
|
||||||
&& header.device_id >= 0x1000
|
virtio_list.push(standard_device);
|
||||||
&& header.device_id <= 0x103F
|
|
||||||
&& standard_device.subsystem_id == 1
|
|
||||||
{
|
|
||||||
return Ok(standard_device);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(VirtioError::VirtioNetNotFound)
|
|
||||||
|
return virtio_list;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,13 @@ pub trait AttributeGroup: Debug + Send + Sync {
|
|||||||
///
|
///
|
||||||
/// 如果返回Some,则使用返回的权限。
|
/// 如果返回Some,则使用返回的权限。
|
||||||
/// 如果要标识属性不可见,则返回Some(ModeType::empty())
|
/// 如果要标识属性不可见,则返回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只读属性文件的权限
|
/// sysfs只读属性文件的权限
|
||||||
|
@ -5,7 +5,7 @@ use core::{
|
|||||||
|
|
||||||
use alloc::{collections::BTreeMap, sync::Arc};
|
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 smoltcp::wire::IpEndpoint;
|
||||||
|
|
||||||
use self::socket::SocketInode;
|
use self::socket::SocketInode;
|
||||||
@ -18,7 +18,7 @@ pub mod syscall;
|
|||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// # 所有网络接口的列表
|
/// # 所有网络接口的列表
|
||||||
/// 这个列表在中断上下文会使用到,因此需要irqsave
|
/// 这个列表在中断上下文会使用到,因此需要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 (全局自增)
|
/// 生成网络接口的id (全局自增)
|
||||||
|
@ -3,10 +3,10 @@ use smoltcp::{socket::dhcpv4, wire};
|
|||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::net::NetDriver,
|
driver::net::NetDevice,
|
||||||
kdebug, kinfo, kwarn,
|
kdebug, kinfo, kwarn,
|
||||||
libs::rwlock::RwLockReadGuard,
|
libs::rwlock::RwLockReadGuard,
|
||||||
net::{socket::SocketPollMethod, NET_DRIVERS},
|
net::{socket::SocketPollMethod, NET_DEVICES},
|
||||||
time::timer::{next_n_ms_timer_jiffies, Timer, TimerFunction},
|
time::timer::{next_n_ms_timer_jiffies, Timer, TimerFunction},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ pub fn net_init() -> Result<(), SystemError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn dhcp_query() -> 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();
|
let net_face = binding.get(&0).ok_or(SystemError::ENODEV)?.clone();
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ fn dhcp_query() -> Result<(), SystemError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_ifaces() {
|
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 {
|
if guard.len() == 0 {
|
||||||
kwarn!("poll_ifaces: No net driver found!");
|
kwarn!("poll_ifaces: No net driver found!");
|
||||||
return;
|
return;
|
||||||
@ -139,8 +139,8 @@ pub fn poll_ifaces() {
|
|||||||
pub fn poll_ifaces_try_lock(times: u16) -> Result<(), SystemError> {
|
pub fn poll_ifaces_try_lock(times: u16) -> Result<(), SystemError> {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < times {
|
while i < times {
|
||||||
let guard: RwLockReadGuard<BTreeMap<usize, Arc<dyn NetDriver>>> =
|
let guard: RwLockReadGuard<BTreeMap<usize, Arc<dyn NetDevice>>> =
|
||||||
NET_DRIVERS.read_irqsave();
|
NET_DEVICES.read_irqsave();
|
||||||
if guard.len() == 0 {
|
if guard.len() == 0 {
|
||||||
kwarn!("poll_ifaces: No net driver found!");
|
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::EAGAIN_OR_EWOULDBLOCK
|
||||||
/// @return 没有网卡,返回SystemError::ENODEV
|
/// @return 没有网卡,返回SystemError::ENODEV
|
||||||
pub fn poll_ifaces_try_lock_onetime() -> Result<(), SystemError> {
|
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 {
|
if guard.len() == 0 {
|
||||||
kwarn!("poll_ifaces: No net driver found!");
|
kwarn!("poll_ifaces: No net driver found!");
|
||||||
// 没有网卡,返回错误
|
// 没有网卡,返回错误
|
||||||
|
@ -7,12 +7,12 @@ use system_error::SystemError;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::rand::rand,
|
arch::rand::rand,
|
||||||
driver::net::NetDriver,
|
driver::net::NetDevice,
|
||||||
kerror, kwarn,
|
kerror, kwarn,
|
||||||
libs::rwlock::RwLock,
|
libs::rwlock::RwLock,
|
||||||
net::{
|
net::{
|
||||||
event_poll::EPollEventType, net_core::poll_ifaces, Endpoint, Protocol, ShutdownType,
|
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());
|
socket_set_guard.get_mut::<raw::Socket>(self.handle.smoltcp_handle().unwrap());
|
||||||
|
|
||||||
// 暴力解决方案:只考虑0号网卡。 TODO:考虑多网卡的情况!!!
|
// 暴力解决方案:只考虑0号网卡。 TODO:考虑多网卡的情况!!!
|
||||||
let iface = NET_DRIVERS.read_irqsave().get(&0).unwrap().clone();
|
let iface = NET_DEVICES.read_irqsave().get(&0).unwrap().clone();
|
||||||
|
|
||||||
// 构造IP头
|
// 构造IP头
|
||||||
let ipv4_src_addr: Option<wire::Ipv4Address> =
|
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())?;
|
PORT_MANAGER.bind_port(self.metadata.socket_type, temp_port, self.clone())?;
|
||||||
|
|
||||||
// kdebug!("temp_port: {}", temp_port);
|
// 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();
|
let mut inner_iface = iface.inner_iface().lock();
|
||||||
// kdebug!("to connect: {ip:?}");
|
// 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_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none"
|
||||||
QEMU_ACCELARATE=""
|
QEMU_ACCELARATE=""
|
||||||
QEMU_ARGUMENT=""
|
QEMU_ARGUMENT=""
|
||||||
|
QEMU_DEVICES=
|
||||||
|
|
||||||
# 如果qemu_accel不为空
|
# 如果qemu_accel不为空
|
||||||
if [ -n "${qemu_accel}" ]; then
|
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_MACHINE=" -machine q35,memory-backend=${QEMU_MEMORY_BACKEND} "
|
||||||
QEMU_CPU_FEATURES+="-cpu IvyBridge,apic,x2apic,+fpu,check,+vmx,${allflags}"
|
QEMU_CPU_FEATURES+="-cpu IvyBridge,apic,x2apic,+fpu,check,+vmx,${allflags}"
|
||||||
QEMU_RTC_CLOCK+=" -rtc clock=host,base=localtime"
|
QEMU_RTC_CLOCK+=" -rtc clock=host,base=localtime"
|
||||||
|
QEMU_DEVICES_DISK="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 "
|
||||||
else
|
else
|
||||||
QEMU_MACHINE=" -machine virt,memory-backend=${QEMU_MEMORY_BACKEND} -cpu sifive-u54 "
|
QEMU_MACHINE=" -machine virt,memory-backend=${QEMU_MEMORY_BACKEND} -cpu sifive-u54 "
|
||||||
|
QEMU_DEVICES_DISK="-device virtio-blk-device,drive=disk "
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ${ARCH} == "riscv64" ]; then
|
if [ ${ARCH} == "riscv64" ]; then
|
||||||
@ -101,7 +105,8 @@ fi
|
|||||||
|
|
||||||
# ps: 下面这条使用tap的方式,无法dhcp获取到ip,暂时不知道为什么
|
# 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 -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
|
# 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_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} "
|
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