1 use super::transport_pci::PciTransport; 2 use super::virtio_impl::HalImpl; 3 use crate::driver::net::virtio_net::virtio_net; 4 use crate::driver::pci::pci::PciDeviceStructureGeneralDevice; 5 use crate::driver::pci::pci::{ 6 get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST, 7 }; 8 use crate::libs::rwlock::RwLockWriteGuard; 9 use crate::{kdebug, kerror, kwarn}; 10 use alloc::{boxed::Box, collections::LinkedList}; 11 use virtio_drivers::transport::{DeviceType, Transport}; 12 const NETWORK_CLASS: u8 = 0x2; 13 const ETHERNET_SUBCLASS: u8 = 0x0; 14 15 //Virtio设备寻找过程中出现的问题 16 enum VirtioError { 17 VirtioNetNotFound, 18 NetDeviceNotFound, 19 } 20 21 /// @brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)(for c) 22 #[no_mangle] 23 pub extern "C" fn rs_virtio_probe() { 24 virtio_probe(); 25 } 26 27 ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加) 28 pub fn virtio_probe() { 29 let mut list = PCI_DEVICE_LINKEDLIST.write(); 30 if let Ok(virtio_list) = virtio_device_search(&mut list) { 31 for virtio_device in virtio_list { 32 match PciTransport::new::<HalImpl>(virtio_device) { 33 Ok(mut transport) => { 34 kdebug!( 35 "Detected virtio PCI device with device type {:?}, features {:#018x}", 36 transport.device_type(), 37 transport.read_device_features(), 38 ); 39 virtio_device_init(transport); 40 } 41 Err(err) => { 42 kerror!("Pci transport create failed because of error: {}", err); 43 } 44 } 45 } 46 } else { 47 kerror!("Error occured when finding virtio device!"); 48 } 49 } 50 51 ///@brief 为virtio设备寻找对应的驱动进行初始化 52 fn virtio_device_init(transport: impl Transport + 'static) { 53 match transport.device_type() { 54 DeviceType::Block => { 55 kwarn!("Not support virtio_block device for now"); 56 } 57 DeviceType::GPU => { 58 kwarn!("Not support virtio_gpu device for now"); 59 } 60 DeviceType::Input => { 61 kwarn!("Not support virtio_input device for now"); 62 } 63 DeviceType::Network => virtio_net(transport), 64 t => { 65 kwarn!("Unrecognized virtio device: {:?}", t); 66 } 67 } 68 } 69 70 /// @brief 寻找所有的virtio设备 71 /// @param list 链表的写锁 72 /// @return Result<LinkedList<&'a mut Pci_Device_Structure_General_Device>, VirtioError> 成功则返回包含所有virtio设备结构体的可变引用的链表,失败则返回err 73 /// 该函数主要是为其他virtio设备预留支持 74 fn virtio_device_search<'a>( 75 list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>, 76 ) -> Result<LinkedList<&'a mut PciDeviceStructureGeneralDevice>, VirtioError> { 77 let mut virtio_list: LinkedList<&mut PciDeviceStructureGeneralDevice> = LinkedList::new(); 78 let virtio_net_device = get_virtio_net_device(list)?; 79 virtio_list.push_back(virtio_net_device); 80 Ok(virtio_list) 81 } 82 83 /// @brief 寻找virtio-net设备 84 /// @param list 链表的写锁 85 /// @return Result<&'a mut Pci_Device_Structure_General_Device, VirtioError> 成功则返回virtio设备结构体的可变引用,失败则返回err 86 fn get_virtio_net_device<'a>( 87 list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>, 88 ) -> Result<&'a mut PciDeviceStructureGeneralDevice, VirtioError> { 89 let result = get_pci_device_structure_mut(list, NETWORK_CLASS, ETHERNET_SUBCLASS); 90 if result.is_empty() { 91 return Err(VirtioError::NetDeviceNotFound); 92 } 93 for device in result { 94 let standard_device = device.as_standard_device_mut().unwrap(); 95 let header = &standard_device.common_header; 96 if header.vendor_id == 0x1AF4 97 && header.device_id >= 0x1000 98 && header.device_id <= 0x103F 99 && standard_device.subsystem_id == 1 100 { 101 return Ok(standard_device); 102 } 103 } 104 Err(VirtioError::VirtioNetNotFound) 105 } 106