xref: /DragonOS/kernel/src/driver/virtio/virtio.rs (revision 13776c114b15c406b1e0aaeeb71812ea6e471d2e)
126d84a31SYJwu2023 use super::transport_pci::PciTransport;
226d84a31SYJwu2023 use super::virtio_impl::HalImpl;
3*13776c11Slogin use crate::driver::net::virtio_net::virtio_net;
478bf93f0SYJwu2023 use crate::driver::pci::pci::PciDeviceStructureGeneralDevice;
578bf93f0SYJwu2023 use crate::driver::pci::pci::{
678bf93f0SYJwu2023     get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST,
778bf93f0SYJwu2023 };
878bf93f0SYJwu2023 use crate::libs::rwlock::RwLockWriteGuard;
926d84a31SYJwu2023 use crate::{kdebug, kerror, kwarn};
1026d84a31SYJwu2023 use alloc::{boxed::Box, collections::LinkedList};
1126d84a31SYJwu2023 use virtio_drivers::transport::{DeviceType, Transport};
12*13776c11Slogin 
1378bf93f0SYJwu2023 const NETWORK_CLASS: u8 = 0x2;
1478bf93f0SYJwu2023 const ETHERNET_SUBCLASS: u8 = 0x0;
1526d84a31SYJwu2023 
1626d84a31SYJwu2023 //Virtio设备寻找过程中出现的问题
1726d84a31SYJwu2023 enum VirtioError {
1826d84a31SYJwu2023     VirtioNetNotFound,
1978bf93f0SYJwu2023     NetDeviceNotFound,
2026d84a31SYJwu2023 }
2126d84a31SYJwu2023 
2226d84a31SYJwu2023 /// @brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)(for c)
2326d84a31SYJwu2023 #[no_mangle]
24*13776c11Slogin pub extern "C" fn rs_virtio_probe() {
2578bf93f0SYJwu2023     virtio_probe();
2626d84a31SYJwu2023 }
2726d84a31SYJwu2023 
2826d84a31SYJwu2023 ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
2978bf93f0SYJwu2023 pub fn virtio_probe() {
3078bf93f0SYJwu2023     let mut list = PCI_DEVICE_LINKEDLIST.write();
3178bf93f0SYJwu2023     if let Ok(virtio_list) = virtio_device_search(&mut list) {
3278bf93f0SYJwu2023         for virtio_device in virtio_list {
3378bf93f0SYJwu2023             match PciTransport::new::<HalImpl>(virtio_device) {
3426d84a31SYJwu2023                 Ok(mut transport) => {
3526d84a31SYJwu2023                     kdebug!(
3626d84a31SYJwu2023                         "Detected virtio PCI device with device type {:?}, features {:#018x}",
3726d84a31SYJwu2023                         transport.device_type(),
3826d84a31SYJwu2023                         transport.read_device_features(),
3926d84a31SYJwu2023                     );
4078bf93f0SYJwu2023                     virtio_device_init(transport);
4126d84a31SYJwu2023                 }
4226d84a31SYJwu2023                 Err(err) => {
4326d84a31SYJwu2023                     kerror!("Pci transport create failed because of error: {}", err);
4426d84a31SYJwu2023                 }
4526d84a31SYJwu2023             }
4626d84a31SYJwu2023         }
4726d84a31SYJwu2023     } else {
4826d84a31SYJwu2023         kerror!("Error occured when finding virtio device!");
4926d84a31SYJwu2023     }
5026d84a31SYJwu2023 }
5126d84a31SYJwu2023 
5226d84a31SYJwu2023 ///@brief 为virtio设备寻找对应的驱动进行初始化
53*13776c11Slogin fn virtio_device_init(transport: impl Transport + 'static) {
5426d84a31SYJwu2023     match transport.device_type() {
5526d84a31SYJwu2023         DeviceType::Block => {
5626d84a31SYJwu2023             kwarn!("Not support virtio_block device for now");
5726d84a31SYJwu2023         }
5826d84a31SYJwu2023         DeviceType::GPU => {
5926d84a31SYJwu2023             kwarn!("Not support virtio_gpu device for now");
6026d84a31SYJwu2023         }
6126d84a31SYJwu2023         DeviceType::Input => {
6226d84a31SYJwu2023             kwarn!("Not support virtio_input device for now");
6326d84a31SYJwu2023         }
6426d84a31SYJwu2023         DeviceType::Network => virtio_net(transport),
6526d84a31SYJwu2023         t => {
6626d84a31SYJwu2023             kwarn!("Unrecognized virtio device: {:?}", t);
6726d84a31SYJwu2023         }
6826d84a31SYJwu2023     }
6926d84a31SYJwu2023 }
7026d84a31SYJwu2023 
7126d84a31SYJwu2023 /// @brief 寻找所有的virtio设备
7278bf93f0SYJwu2023 /// @param list 链表的写锁
7378bf93f0SYJwu2023 /// @return Result<LinkedList<&'a mut Pci_Device_Structure_General_Device>, VirtioError>  成功则返回包含所有virtio设备结构体的可变引用的链表,失败则返回err
7426d84a31SYJwu2023 /// 该函数主要是为其他virtio设备预留支持
7578bf93f0SYJwu2023 fn virtio_device_search<'a>(
7678bf93f0SYJwu2023     list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
7778bf93f0SYJwu2023 ) -> Result<LinkedList<&'a mut PciDeviceStructureGeneralDevice>, VirtioError> {
7878bf93f0SYJwu2023     let mut virtio_list: LinkedList<&mut PciDeviceStructureGeneralDevice> = LinkedList::new();
7978bf93f0SYJwu2023     let virtio_net_device = get_virtio_net_device(list)?;
8078bf93f0SYJwu2023     virtio_list.push_back(virtio_net_device);
8126d84a31SYJwu2023     Ok(virtio_list)
8226d84a31SYJwu2023 }
8378bf93f0SYJwu2023 
8478bf93f0SYJwu2023 /// @brief 寻找virtio-net设备
8578bf93f0SYJwu2023 /// @param list 链表的写锁
8678bf93f0SYJwu2023 /// @return Result<&'a mut Pci_Device_Structure_General_Device, VirtioError> 成功则返回virtio设备结构体的可变引用,失败则返回err
8778bf93f0SYJwu2023 fn get_virtio_net_device<'a>(
8878bf93f0SYJwu2023     list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
8978bf93f0SYJwu2023 ) -> Result<&'a mut PciDeviceStructureGeneralDevice, VirtioError> {
9078bf93f0SYJwu2023     let result = get_pci_device_structure_mut(list, NETWORK_CLASS, ETHERNET_SUBCLASS);
9178bf93f0SYJwu2023     if result.is_empty() {
9278bf93f0SYJwu2023         return Err(VirtioError::NetDeviceNotFound);
9378bf93f0SYJwu2023     }
9478bf93f0SYJwu2023     for device in result {
9578bf93f0SYJwu2023         let standard_device = device.as_standard_device_mut().unwrap();
9678bf93f0SYJwu2023         let header = &standard_device.common_header;
9778bf93f0SYJwu2023         if header.vendor_id == 0x1AF4
9878bf93f0SYJwu2023             && header.device_id >= 0x1000
9978bf93f0SYJwu2023             && header.device_id <= 0x103F
10078bf93f0SYJwu2023             && standard_device.subsystem_id == 1
10178bf93f0SYJwu2023         {
10278bf93f0SYJwu2023             return Ok(standard_device);
10378bf93f0SYJwu2023         }
10478bf93f0SYJwu2023     }
10578bf93f0SYJwu2023     Err(VirtioError::VirtioNetNotFound)
10678bf93f0SYJwu2023 }
107